Azure-Kubenetes-服务入门指南-全-
Azure Kubenetes 服务入门指南(全)
一、Docker 容器内部
欢迎来到【Azure Kubernetes 服务简介:容器编排实用指南。在进入 Azure Kubernetes 服务之前,了解通向 Kubernetes 和最终 Azure Kubernetes 服务的构件和道路是很重要的。
这一章并没有深入探讨 Docker 和用 Docker 构建应用。Docker 是一个很大的主题,可以写满一整本书。本章的目的是给那些不熟悉 Docker 的人足够的入门知识,也给那些熟悉 Docker 的人一个复习的机会,这是 Kubernetes 必备的知识。
在第一章中,我们将深入 Docker 容器。到本章结束时,你会对 Docker 有更深的了解;映像;容器及其价值;底层 Docker 组件;如何安装 Docker,运行 Docker 命令,构建 Docker 镜像;和 Docker Compose,最后介绍编排平台。
容器的价值
容器化并不新鲜。事实上,自 20 世纪 80 年代以来,容器技术已经出现在 Linux 世界中。然而,部分由于 2013 年 Docker 容器格式的推出,容器才随着巨大的增长而变得广泛流行。
容器是隔离的用户空间实例中应用层的抽象。容器共享运行它们的主机上的操作系统(OS)内核存储和网络。容器可以被认为是作为一个进程运行的应用所需要的核心组件。容器允许打包应用及其在实例中运行的依赖项。容器允许软件工程师开发他们的应用,并以一致的方式跨环境(如开发、试运行和生产)进行复制。容器可以通过持续集成和持续部署流水线,以保持操作系统、依赖性和应用不变的方式移动,从而提供最终的灵活性和敏捷性。
从技术角度来看,容器的价值可以归结为以下几点:在相同硬件上的应用密度比任何其他技术都大,对开发人员的优化提高了开发人员的工作效率和流水线,操作简单,以及与云和基础设施无关,实现了真正的平台独立性和最终的可移植性。
容器对企业的价值在于降低总拥有成本、加快上市速度、提高客户满意度、可预测性和可靠性、增加灵活性以及提高运营速度。
什么是 Docker
有许多可用的容器格式;然而,Docker 已经成为 Windows 和 Linux 容器事实上的标准。Docker 是一种开源的容器格式。Docker 可以用来构建、运行和存储容器映像和容器。根据 Docker,350 多万个应用已被容器化。根据 RightScale 2018 年云状况报告,2018 年 Docker 的采用率从 35%上升到 49%。让我们深入了解 Docker 组件:
-
Docker 引擎是 Docker 解决方案的核心。它是一个客户端-服务器应用,具有以下组件:
-
Docker 客户端是用户与 Docker 交互的方式。Docker 客户端自带命令行界面(CLI),用户可以在其中执行 Docker 命令。Docker 客户端可以与 Docker 守护程序或客户端计算机运行在同一台计算机上,并远程连接到 Docker 守护程序。
-
Docker 主机运行 Docker 守护进程。Docker 守护进程是管理 Docker 映像、容器、网络和存储卷的后台进程。守护进程监听 REST API 上的命令或通过 CLI 接收命令。它还可以与其他 Docker 守护进程通信,以管理 Docker 服务。
-
Docker registry 是一个存储库服务,您可以在其中托管和下载容器映像。Docker 注册表可以是本地的、公共的或私有的。Docker 有一个名为 Docker Hub 的公共注册服务。大多数云提供商都提供私有 Docker 注册表。
-
-
Docker 对象
-
Docker 映像是用于构建 Docker 容器的只读模板。其中包含创建 Docker 容器的说明。映像包括应用代码、运行时、系统库、系统工具和设置。
-
Docker 容器就是运行时运行的映像。Docker 容器运行在 Docker 引擎上。
-
Docker 服务允许容器跨多个 Docker 守护进程伸缩。这些多个守护进程与多个管理器和工作器一起作为一个群体。
-
Docker 有两个版本:
-
社区版(CE)
- 对于开发人员、小型团队和任何从容器开始的人来说,CE 是一个很好的选择。
-
企业版(EE)
- EE 适合企业团队和生产需求。
要知道 Kubernetes 支持多容器运行时是很重要的;然而,总体 Docker 是当今技术领域最常见的映像和容器格式。花些时间深入学习 Docker 是值得的。
容器与虚拟机
在 IT 领域,当需要建立一台服务器来运行应用时,虚拟机(VM)几乎成了标准。虚拟机需要虚拟机管理程序才能运行。有许多虚拟机管理程序,但最受欢迎的是 VMWare 和 Hyper-V。虚拟机管理程序安装在物理机之上,然后虚拟机部署在虚拟机管理程序之上。这使得 IT 行业可以在物理服务器上打包许多虚拟机,从而提高密度并从物理硬件中获得更多投资回报。虚拟机模拟物理服务器,包括存储、网络和操作系统。它们比物理服务器更便携、更快,但仍然是完整的服务器,需要启动时间和与物理服务器相同的管理级别。
容器将密度和优化提升到了一个新的高度。容器仍然是虚拟化的一种形式,但只是虚拟化了运行应用的核心。有了容器,就不需要管理程序了,因为它们直接在内核上运行。您可以在一台物理服务器上打包更多的容器。容器更加轻量级,启动速度更快,管理也更加简化。
对于容器,一些底层组件在运行于主机上的所有容器之间共享,例如存储和网络。图 1-1 给出了容器和虚拟机之间架构差异的可视化表示。
图 1-1
容器与虚拟机
从图中可以看出,容器是在操作系统级别的过程中被隔离的,而虚拟机是在硬件抽象层被隔离的。容器的增长并不意味着虚拟机将很快消失。由于好处,你有理由使用容器而不是虚拟机。让我们看看使用容器的一些原因:
-
速度 : Docker 容器与虚拟机相比速度极快。启动一个容器可能需要几毫秒到几秒钟的时间,而启动一个虚拟机至少需要几分钟。
-
可移植性:容器可以在多个团队、开发流水线、云和基础设施之间移动和共享,无论容器在哪里运行,应用的行为都是一样的。这减少了人为错误和潜在的环境依赖性错误。
-
微服务:容器是分离和运行应用组件以支持基于微服务的架构的好方法。
-
现在让我们来看看您可能仍然希望使用虚拟机而不是容器的一些原因。
-
有状态的:如果你有需要状态的应用,虚拟机可能是更好的选择,因为容器是为运行无状态应用而设计的。
-
协同定位:如果一个应用组件必须全部安装在同一台服务器上,虚拟机将是一个更好的选择,因为容器的焦点通常是将一个应用的服务分散到多个容器中。
随着容器的增加,虚拟机的占用空间将会减少。然而,虚拟机不会消失,因为仍然有它们的使用案例,并且今天许多工作负载在虚拟机上运行得很好。
映像和容器
在这一章的前面,容器映像和容器之间的区别已经被简要地讨论过了。让我们更深入地了解什么是映像和容器。简而言之,容器就是一个映像的运行实例。
映像是只读的。可以通过更改来修改容器,但是当容器停止时,这些更改会丢失。如果将容器的更改提交给新映像,则可以保留这些更改。映像是代码、运行时、文件系统、库和设置的表示。映像是一个名为 Dockerfile 的文件中的一组命令,它定义了容器内部的环境。清单 1-1 是一个简单的映像 Dockerfile 文件的例子,它运行在 Ubuntu Linux 操作系统上,并执行一个命令来输出 Hello World!。
FROM ubuntu:latest
CMD echo Hello World!
Listing 1-1Dockerfile content
构建 docker 文件后,docker build 命令用于构建实际的映像。默认情况下,构建的 docker 映像存储在本地,可以从本地作为容器运行,也可以推送到 Docker 注册表。默认情况下,Docker 映像会获得一个唯一的 ID,但是可以对其进行命名和标记。这就结束了 Docker 映像和容器的总结。在本章的后面,我们将使用 docker 构建和运行一个容器来更详细地研究 docker 文件。
Docker 组件(网络和存储)
建立关系网
在您的容器之旅中,您将到达需要向外部世界公开它的地方,或者您可能需要将同一主机上或跨其他主机的几个容器连接在一起。Docker 容器有适合所有场景的网络选项。容器技术中有一个网络层,用于容器与其他容器、主机和外部世界进行通信。Docker 支持几种不同类型的网络。让我们看看每种类型的网络,以便更好地理解网络在容器中是如何工作的:
-
网桥是容器的默认网络。当 Docker 启动时,会创建一个桥接网络,除非另外指定,否则容器会连接到这个网络。对于这种网络类型,外部世界访问容器需要端口映射。这种网络类型适用于在同一 Docker 守护进程主机上运行的容器。如果容器需要与运行在其他守护程序主机上的容器通信,则需要在操作系统级别进行路由,或者应该使用覆盖网络类型。
-
主机直接使用主机的网络。将使用主机的 IP 地址访问容器。这种网络类型仅适用于 Linux 主机。Docker 桌面不支持此功能。这种网络类型也用于 swarm。
-
Overlay 也称为 ingress,它将 Docker 守护程序连接在一起,用于多主机网络通信。覆盖类型在物理网络之上运行几层网络抽象。覆盖网络是托管在多个 Docker 主机上的容器中的单个第 2 层广播域。
-
Macvlan 允许您将 MAC 地址直接分配给容器。当使用 Macvlan 时,容器看起来就像在网络上一样。当使用这种方法时,可以为容器分配一个可从外部访问的公共 IP 地址。这种类型的网络将容器连接到主机网络接口。这种类型使用第 2 层分段,不需要网络地址转换(NAT)或端口映射。
仓库
容器可以存储对它们所做的更改。任何容器更改都将保存到可写层。此可写层需要存储驱动程序来存储这些更改。默认情况下,容器有非持久存储。非持久性意味着当容器重启时,存储被销毁。为了在容器重启或关闭时无限期保留数据,需要持久存储。使用 Docker 容器,我们有四个持久存储选项。持久存储选项包括
-
数据卷位于容器外部的主机文件系统上。这些允许您创建持久存储和管理卷,例如列出它们、列出它们关联的容器以及重命名它们。
-
数据卷容器是指一个容器专用于托管其他容器的卷。您可以将该容器中的卷装入其他容器中。例如,您可能有一个承载应用的应用容器和一个承载应用容器的卷的卷容器。
-
目录装载是指将主机的本地目录装载到容器中。
-
存储插件与底层存储设备一起工作,并且可以连接到外部存储解决方案。这可以映射到外部存储解决方案,包括云提供商 Azure、AWS 和 GCP;存储阵列,如 EMC、HPE 3PAR 和 NetApp 和存储设备。
安装 Docker
当您开始使用 Docker 时,您需要在本地机器上安装 Docker Desktop。Docker 桌面通常用于本地开发目的。Docker 桌面包括 Docker 引擎、Docker 客户端、Docker 合成、Docker 机器和 Kitematic。Kitematic 是我们还没有讨论过的东西。Kitematic 是一个用于 Docker 映像和容器的 GUI。Kitematic 还自动完成 Docker 的安装和设置过程。
Docker 是跨平台的,因此它可以安装在 Linux、Mac 或 Windows 上。在这一节中,我们将介绍在 Windows 上安装 Docker 的步骤。让我们直接进入在 Windows 上安装 Docker 的步骤。
要求:
-
集群和节点管理
-
Windows 10,64 位:专业版、企业版或教育版(内部版本 15063 或更高版本)
-
在 BIOS 中启用虚拟化
-
支持 CPU SLAT 的功能
-
微软超级 V
-
至少 4 GB 内存
安装步骤:
-
下载坞站桌面安装程序. exe 来自
https://download.docker.com/win/stable/Docker%20for%20Windows%20Installer.exe
。 -
双击 Docker 桌面 Installer.exe运行安装程序。
-
将弹出一个向导。按照向导中的步骤操作,包括接受许可证、授权安装程序并继续安装。
-
单击“完成”以完成 Docker 桌面安装。
-
Docker 不会自动启动。需要启动 Docker。为此,请使用 Windows search 搜索 Docker。单击 Docker 桌面 Windows 版。
注意
如果 Hyper-V 没有启用,Docker 桌面安装程序将自动启用它,并在需要时重新启动计算机。
您可以设置 Docker Desktop 在登录 Windows 时自动启动,如图 1-2 所示。
图 1-2
登录时启动 Docker 桌面设置
安装 Docker 后,您应该在任务栏中看到 Docker 图标,以反映 Docker 已安装并正在运行。让我们在接下来的部分中更深入地利用 Docker。
Docker 命令备忘单
与 Docker 的交互是通过命令行完成的。Docker 是用 Go 写的。Docker 将其配置文件存储在一个名为. docker 的目录中,让我们来分解一下 docker 命令结构。所有 docker 命令都是以docker
开头,然后有一个空格然后是命令,另一个空格,然后是管理类别或者选项。docker 管理命令语法如图 1-3 所示。
图 1-3
Docker 管理指挥结构
直接引用容器的 Docker 命令略有不同。命令以docker,
开始,然后有一个空格,然后是命令,另一个空格,然后是容器名。参考特定容器的 docker 命令语法可以在图 1-4 中看到。
图 1-4
Docker 命令结构
以下是您在开始使用 Docker 时应该知道的关键 Docker CLI 命令列表:
-
docker 信息:这将显示 Docker 的系统范围信息。
-
docker 版本:这将列出您当前的 Docker 版本。
-
docker [COMMAND] help:这将列出一个命令的帮助信息。
-
docker images:这将列出本地系统上的映像。
-
docker run:这将创建并运行一个基于映像的容器。
-
docker start:这将启动一个现有的容器。
-
停靠站:这将停止一个正在运行的容器。
-
docker build:用于从 docker 文件构建映像。
-
docker 登录:这将使你登录到 Docker 注册表。
-
docker 注销:这将使你从 Docker 注册表中注销。
-
docker pull:这将从容器注册表中提取一个映像。
-
docker ps:这将列出正在运行的容器。
-
docker inspect:这将显示一个容器的所有信息,包括 IP 地址。
-
docker rm:这将删除一个映像。
-
docker 日志:这将打印 docker 日志。
了解 Dockerfile 文件
Dockerfile 由一组用于构建映像的指令组成。Dockerfile 应命名为“Dockerfile ”,不带扩展名。从 docker 文件构建映像时,需要包含在映像中的所有文件都应该与 docker 文件位于同一个文件夹中。以下是 Dockerfile 文件的一个示例:
FROM python:alpine3.7
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5000
CMD python ./index.py
让我们分解示例 Dockerfile 中的命令,以便更好地理解 Dockerfile 结构
-
FROM :定义用于容器的基本映像。
-
COPY :将文件从源文件复制到容器中。
-
WORKDIR :设置执行 CMD 定义的命令的路径。
-
RUN :这定义了一组在容器首次创建时运行的命令。
-
EXPOSE :这将向外界公开一个端口,以支持对容器的网络访问。
-
CMD :运行时会在容器内执行一个特定的命令。
docker build 命令被用作从 docker 文件自动构建映像的一种方式。在下一节中,我们将进一步了解 docker 构建。
了解 Docker 版本
如前所述,docker build 是运行从 docker 文件创建映像的过程的命令。这应该在包含 Dockerfile 文件的同一个目录中运行。以下是 docker 构建语法的一个示例:
docker build --tag pythonapp:dev
标签和:dev 将使用名称和 dev 来标记映像。这使得识别映像更加容易。标签是记录容器映像的变体和/或版本信息的一种方式。可以把标签想象成给容器映像添加一个别名。在映像构建过程运行之后,您可以运行docker images
来列出映像并验证您的名称映像是否已创建。
了解复合坞站
Dockerfile 是单个映像。您可以使用 Dockerfile 创建单个映像来运行单个容器。如果您需要创建一个多容器应用,其中的容器相互连接,那么您可以使用一个名为 Docker Compose 的工具。我们不会深入讨论 Docker Compose,因为这是一个高级主题,不在本章讨论范围之内。然而,我们将给出 Docker 编写的概述。
Docker 编写文件在 YAML。在 Docker 合成文件中,您引用映像;因此,您仍然需要在 Dockerfiles 中构建容器映像。使用 Docker Compose,您可以运行一个命令来一次性启动组成您的应用的所有容器。下面是 docker-compose.yml 文件中的一个基于多容器的 WordPress 应用的例子,它由一个 WordPress 站点和一个后端 MySQL 数据库服务器组成:
version: '1.0'
services:
db:
image: mysql:latest
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: secret3241
MYSQL_DATABASE: wp
MYSQL_USER: wpadmin
MYSQL_PASSWORD: secret3241
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wpadmin
WORDPRESS_DB_PASSWORD: secret3241
WORDPRESS_DB_NAME: wp
volumes:
db_data: {}
Docker Compose 基本上分以下三个步骤工作:
-
用 Dockerfiles 定义所需的容器映像。
-
在 docker-compose.yml 文件中定义组成多容器应用的服务。
-
在包含 docker-compose.yml 文件的目录中运行 docker-compose up 命令,以启动并运行多容器应用。
运行容器
您已经学习了如何创建容器映像。您学习了 docker 文件,然后学习了如何使用 docker build 创建映像以及如何列出映像。下一步是从映像创建并运行容器。您可以运行以下语法来创建和构建容器:
docker run pythonapp:dev
第一次创建容器后,不能使用 docker stop pythonapp:dev
和docker start pythonapp:dev
停止和启动容器。
编排平台
通过这一章,到目前为止,你已经学习了所有关于容器、Docker 和容器化的许多方面。在开发软件时,构建容器映像和运行容器是相当简单的。在生产、企业就绪和大规模环境中运行数百甚至数千个容器化的应用,需要一套不同的工具和技能,目前尚未讨论。当您需要在生产中运行容器时,容器编排平台就进入了画面。容器编排就是管理容器的生命周期。生产容器环境是动态的,需要高度自动化。容器业务流程句柄
-
集群和节点管理
-
容器供应和部署
-
容器配置和调度
-
容器可用性和冗余
-
集群节点和容器的自动扩展
-
容器负载均衡、流量路由、外部访问和服务发现
-
容器的资源管理和移动
-
容器和主机运行状况和性能监控
-
容器安全和出入管理
编排系统需要覆盖很多领域来处理容器的生命周期管理。市场上有许多容器编排平台。顶级容器编排平台是 Docker Swarm、Docker Enterprise、Mesosphere、OpenShift 和 Kubernetes。Kubernetes 是 Google 开发的一个开源编排平台。Kubernetes 已经迅速成为容器编排事实上的标准。三大云提供商微软、亚马逊和谷歌都在其云平台上提供托管 Kubernetes 服务。在本书的其余部分,我们将深入探讨 Kubernetes,特别是 Azure Kubernetes 服务。
注意
Docker Compose 通常被称为编排工具;然而,同样重要的是要注意,与运行许多节点的编排平台相比,Docker Compose 是针对专用的单个节点的。
摘要
这使我们结束了第一章。在这一章中,我们进入了 Docker 容器的世界,因为这些信息是进入 Kubernetes 和最终的 Azure Kubernetes 服务的基础。在第一章中,我们特别介绍了容器的价值,容器与虚拟机的比较,所有关于 Docker 本身的内容,包括如何安装它,Docker 所需的核心命令,以及所有关于创建和运行容器映像的内容。最后,在本章中,我们略微谈到了容器编排平台。
二、容器注册表
Kubernetes 用于部署基于容器的应用和服务。在许多方面,基于容器的应用推动了对像 Kubernetes 这样的容器编排技术的需求。如前一章所述,容器是从一个名为映像的只读副本实例化的。映像通常存储在一个称为容器注册表的结构中。
在本章中,我们将讨论映像存储、管理和分发的各种选项。我们将研究不同类型的容器注册中心,特别是 Azure 容器注册中心(ACR)。本章结束时,你将能够对容器注册表执行基本操作,并理解映像标记、安全性和权限等概念。
注意
为了简单起见,我们将把重点放在使用开放容器倡议(OCI)映像规范和容器运行时的映像上。还有其他容器映像格式(ACI)和容器运行时(rkt),但基本概念保持不变。
容器登记概述
当您将应用部署到 Kubernetes 集群时,该应用将由一个或多个容器组成。Kubernetes 需要能够访问这些映像,以便在 Kubernetes 集群中的每个节点上实例化这些容器。您可以在工作站上创建一个映像,并手动将其复制到每个节点,然后在每次更新映像时重复该过程。但是这将会非常低效,容易出错,并且不可扩展。一个更好的解决方案是共享一个位置,所有节点都可以从该位置访问映像并将其下载到本地映像缓存中。这是容器注册背后的基本原则。
注册表、存储库和映像
在我们深入研究容器注册中心之前,理解注册中心、存储库和映像之间的区别是很有用的。正如我们在第一章“Docker 容器内部”中提到的,容器映像是一个只读的构造,容器就是从这个构造实例化的。每个映像都有一个名称和与之关联的可选标签。让我们看看清单 2-1 中所示的从 Docker Hub 中提取映像的例子。
REPOSITORY TAG IMAGE ID
Nginx latest 53f3fd8007f7
Listing 2-1Image listing of nginx container image
映像来自于nginx
存储库。它已经被标记为latest
。并且它有一个唯一的映像 ID。nginx 存储库中存储了其他映像,包括一个标记为 alpine 的映像和另一个标记为 perl 的映像。在提取这两个映像之后,docker image ls
的更新输出如清单 2-2 所示。
REPOSITORY TAG IMAGE ID
nginx alpine dd025cdfe837
nginx perl 4d95835f5c94
nginx latest 53f3fd8007f7
Listing 2-2Image listing of nginx container images
每个映像都来自同一个存储库,但是它们都有不同的标签和映像 id。它们是独一无二的映像。我们将在本章的后面深入探讨标签以及它与映像的关系。
总之,容器存储库包含一个或多个映像。容器注册中心包含一个或多个存储库。特定存储库中的映像可能彼此相关,也可能不相关。
私有和公共注册和存储库
当选择容器注册中心来存放映像时,第一个问题通常是创建私有还是公共注册中心。一个公共注册中心托管在互联网上,任何人都可以访问。它可能包含注册管理机构内公共和私有存储库的混合。一个私有注册中心托管在一个内部网络上,并且只对内部网络上的系统和用户开放。私有注册中心中的存储库也可以包含公共和私有存储库的混合,但是在这种情况下,公共存储库的范围必然受到更多的限制,因为它只对内部网络上的资源可用。虽然大多数公共注册管理机构是作为托管服务运行的,但私有注册管理机构通常由托管注册管理机构的内部 IT 团队管理。
任何能够访问注册中心网络位置的人都可以访问公共存储库中的映像。这并不意味着任何人都可以从存储库中添加、更新或删除映像,但是他们可以下载映像而无需任何类型的身份验证。私有存储库中的映像要求任何希望访问该存储库的人都要经过身份验证,并被授予下载映像的相关权限。
公共注册和存储库最常用于发布开源项目和软件,这些项目和软件是为了与全世界共享。例如,Docker Hub 上的微软存储库是公开的,用于发布像微软/点网和微软/powershell 这样的应用的基本映像。很明显,微软希望你能下载这些图片,并用它们来建造一些令人惊奇的东西。
一些常见的公共注册表有
-
坞站集线器
-
谷歌容器注册
-
Azure 容器注册表
-
亚马逊弹性容器注册中心
当映像需要保存在公司或组织内部,并且对这些映像的访问应该受到控制时,可以使用私有注册表和私有存储库。此外,私有注册管理机构通常托管在内部网络上,无法通过更广泛的互联网进行访问。您的映像可能安装了被视为重要知识产权的专有软件。例如,假设您的公司正在开发基因组学软件,并使用容器进行部署。这些映像将包含非常有价值的算法,不应该提供给竞争对手。因此,您可以选择将您的映像保存在私有存储库中,也可能保存在私有注册表中。
一些常见的私有注册中心有
-
可信注册表坞站
-
JFrog Artifactory
-
海港
-
GitLab
基本注册表操作
所有容器注册中心都支持相同的基本操作。这些操作包括
-
登录注册表以与映像存储库交互
-
在映像库中搜索特定映像
-
将映像下载到本地文件系统
-
将映像推送到注册中心托管的映像存储库
在下面的例子中,我们将展示针对 Docker Hub 执行的操作。您可以免费创建一个 Docker Hub 帐户,并按照示例进行操作。
注册
使用 Docker CLI 可以登录到容器注册中心。以下命令将启动登录过程。
docker login [SERVER]
SERVER
值可以引用您想要登录的任何注册表。该命令还接受提供一个username
和password
。如果没有指定SERVER
值,Docker CLI 将认为您正在登录 Docker Hub。清单 2-3 展示了一个使用账户 iaks 登录 Docker Hub 的例子。
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don’t have a Docker ID, head over to https://hub.docker.com to create one.
Username: iaks
Password: ************
Login Succeeded
Listing 2-3Logging into Docker Hub
搜索
Docker Hub registry 有超过 100,000 个容器映像可供公众使用。显然,私人注册中心的映像要少得多,但是需要能够搜索可用的映像来找到满足您需求的映像。docker search
命令提供了这一功能。该命令的语法是
docker search [OPTIONS] TERM
假设我们正在寻找一个 nginx 映像来运行和托管一个 web 服务器。这样做的搜索命令如清单 2-4 所示。
$ docker search nginx
NAME DESCRIPTION STARS OFFICIAL
nginx Official build of Nginx. 11498 [OK]
.
.
[output truncated]
Listing 2-4Searching Docker Hub for nginx images
默认情况下,Docker CLI 将在 Docker Hub 注册表中搜索映像。可以通过在搜索中包含地址来搜索其他注册中心TERM
。在执行搜索命令之前,您需要通过您试图搜索的注册表的身份验证。
拉
从容器注册表中提取映像是将托管映像下载到本地文件存储库的行为。Docker 守护程序使用的存储驱动器决定了文件的存储位置。当提取映像时,Docker 首先检查映像中包含的层,以确定是否已经下载了任何层。任何尚未在本地缓存的图层都将从源资料档案库中下载。清单 2-5 显示了一个在本地文件系统中已经存在一个图层的情况下提取高山/地形地貌映像的例子。
$ docker pull alpine/terragrunt
Using default tag: latest
latest: Pulling from alpine/terragrunt
e7c96db7181b: Already exists
622c94c90cb1: Pull complete
[output truncated]
68ced3bc2ce4: Pull complete
Digest: sha256:4363c7ea68ae6b648d803753884afed380f106eb23e902641ae919b7b02fe95a
Status: Downloaded newer image for alpine/terragrunt:latest
docker.io/alpine/terragrunt:latest
Listing 2-5Pulling the alpine/terragrunt image from Docker Hub
在公共注册的情况下,任何人都可以提取映像,无论他们是否经过身份验证。对于私有注册中心,用户必须首先经过身份验证,并且拥有获取给定映像的权限。
可以通过发出 docker pull 命令来提取映像。语法如下:
docker pull [OPTIONS] NAME[:TAG | @DIGEST]
名称是指映像的名称。Docker 将假设源存储库在 Docker Hub 上,除非它已经被另外配置,或者名称包括不同的注册中心。例如,可以通过运行以下命令从微软的公共容器注册表中提取映像
docker pull mcr.microsoft.com/azuredocs/aci-helloworld
如果没有指定TAG
,那么 docker 将获取存储库中标记为最新的映像。最新的标签没有什么特别的,这并不意味着提取的映像实际上将是最新的或最新的映像。一般来说,最好指定一个标签和要提取的映像的名称。
推
推送是获取本地映像并将其复制到目标存储库的行为。存储库可以位于公共或私有注册中心。在任何一种情况下,这两种类型的注册中心在允许复制映像之前都需要身份验证和适当的授权。
可以使用docker build
命令从 Dockerfile 文件创建一个新的映像,然后将其推送到目标注册表。还可以使用从单独的存储库中提取的现有映像,并将其推送到不同的存储库中。清单 2-6 展示了一个可以用来构建新映像的 Dockerfile 文件示例。
FROM nginx:stable-alpine
COPY IAKS /usr/share/nginx/html
Listing 2-6Dockerfile content
FROM
命令将从 nginx 存储库中提取标记为 stable-alpine 的 nginx 映像。COPY
命令会将 IAKS 目录的内容复制到路径/usr/share/nginx/html 中。我们可以通过从包含 Dockerfile 的目录中运行以下命令来创建这个新映像:
docker build --tag iaks/nginx:v1.
通过将其命名为iaks/nginx:v1
,我们表明该映像的目标存储库将是 iaks Docker Hub 帐户,映像的名称是 nginx。我们将其标记为 v1,目前这是一个任意的标记。通过运行docker image ls
,我们可以看到,在清单 2-7 中,我们现在在本地文件系统上有了一个新的镜像。
$ docker image ls
REPOSITORY TAG IMAGE ID
iaks/nginx v1 bbbdb4e15efd
Listing 2-7Listing the image created by docker build
最后,我们可以通过运行docker push
命令将映像从本地文件系统推送到 Docker Hub 存储库。该命令的语法是
docker push [OPTIONS] NAME[:TAG]
在这种情况下,我们将运行清单 2-8 中所示的命令来推送映像。
$ docker push iaks/nginx:v1
The push refers to repository [docker.io/iaks/nginx]
7dd2de43c03e: Pushed
2bdf88b2699d: Mounted from library/nginx
f1b5933fe4b5: Mounted from library/nginx
v1: digest: sha256:00caf...f4997cea1 size: 94
Listing 2-8Pushing the image to Docker Hub
通过浏览器查看我们的 Docker Hub 帐户,我们可以在图 2-1 中看到,映像已经被成功地推送到我们的存储库。
图 2-1
成功将映像推送到 Docker Hub
现在可以提取这个映像,并在任何可以访问互联网的容器主机上运行它。这包括 Azure Kubernetes 服务集群中的工作节点。
映像标记
映像标签是与特定映像相关联的附加元数据。正如我们在注册表、存储库和映像一节中看到的,映像有一个存储库、标签和 ID。在清单 2-9 中,已经提取了三个 nginx 映像,它们都有不同的标签和映像 id。
REPOSITORY TAG IMAGE ID
nginx alpine dd025cdfe837
nginx perl 4d95835f5c94
nginx latest 53f3fd8007f7
Listing 2-9Listing of different nginx images
通过使用docker image tag
命令,可以将多个标签与单个映像相关联。向映像添加另一个标记不会创建新的映像,也不会占用本地文件系统的更多空间。Docker 只是将这个新的元数据信息分配给现有的映像 ID。docker image tag
命令的语法如下:
docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
例如,我们可以获取现有的 nginx:alpine 映像,并用 v1 标记它。
docker image tag nginx:alpine nginx:v1
在查看清单 2-10 中的本地映像清单时,两个映像都存在,并且具有相同的映像 ID。
$ docker image ls
REPOSITORY TAG IMAGE ID
nginx alpine dd025cdfe837
nginx v1 dd025cdfe837
nginx perl 4d95835f5c94
nginx latest 53f3fd8007f7
Listing 2-10Logging into Docker Hub
我们还可以为完全不同的存储库标记映像,然后将映像推送到该存储库。
docker image tag nginx:alpine iaks/custom
清单 2-11 中显示的三个条目将具有相同的映像 ID。
$ docker image ls
REPOSITORY TAG IMAGE ID
nginx alpine dd025cdfe837
nginx v1 dd025cdfe837
iaks/custom latest dd025cdfe837
Listing 2-11Logging into Docker Hub
标签只是与映像相关联的元数据。这包括神秘的最新的标签。如果没有为映像提供标签——就像我们在前面的命令中所做的那样——Docker 会自动给它一个最新的标签。当一个映像被拉取或用于实例化一个容器时,如果没有提供其他标签,Docker 将同样采用最新的标签。 latest 标签并不意味着被拉取的映像是最新的或者甚至是合适的映像。它只是映像被贴上了最新的标签,不管是故意的还是疏忽的。因此,在提取映像或运行容器时,总是建议指定映像的标签。
通用注册表
坞站中心和坞站注册表
用户最常开始使用的注册中心是 Docker Hub,如图 2-2 所示。Docker Hub 托管在 docker.io 上,为新用户提供了一个免费的家,让他们可以开始使用自己的第一个存储库。除非另外配置,否则 Docker CLI 假定 Docker Hub 是正在使用的注册中心。许多软件公司选择在 Docker Hub 上托管他们公开可用的容器,一些开源项目也是如此。Docker Hub 支持公共和私有存储库,尽管私有存储库不是免费的。
图 2-2
坞站中心网站
Docker Hub 基于开源项目 Docker Registry。Docker Registry 还可以用于在数据中心部署私有注册表。微软使用 Docker Registry 项目作为他们部署 Azure 容器注册表的基础,其他几个公共和私有注册表实现也是如此。
Azure 容器注册表
Azure Container Registry (ACR)是微软托管在 Azure 上的软件即服务产品。ACR 是基于 Docker Registry 开源项目的,但是它有额外的功能,我们将在本章的后面探讨。在 ACR 上创建的存储库本质上是私有的,并且总是需要某种类型的身份验证才能访问。ACR 有几个不同的 SKU 可供选择——基本、标准和高级——更高层提供更强大的存储、性能和复制选项。
存储在 ACR 上的映像可以是以下格式:
-
Docker 映像清单 V2,模式 1
-
Docker 映像清单 V2,模式 2
-
开放容器映像格式规范
ACR 服务还可以托管掌 Helm 图表,我们将在第 8 、【Azure Kubernetes 服务的掌 Helm 图表中对此进行更多探讨
为了在 ACR 上创建注册中心,你需要一个 Azure 订阅。可以通过 Azure 门户、Azure PowerShell 或 Azure CLI 创建新的 ACR 注册表。本节剩余部分和下一节中的示例将使用 Azure CLI。
清单 2-12 中的命令将使用 Azure CLI 创建一个新的 ACR 注册表。
### Create an Azure Container Registry ###
# Login to Azure and select subscription
az login
az account set --subscription "AZURE_SUBSCRIPTION_NAME"
# Create a resource group and Container Registry
az group create --name RESOURCE_GROUP_NAME --location "LOCATION_NAME"
az acr create --resource-group RESOURCE_GROUP_NAME --name ACR_NAME --sku Basic
Listing 2-12Creating a new ACR registry
ACR_NAME 必须是全局唯一的。它将被附加到 azurecr.io 中,为您的注册表创建公开寻址的 fqdn。
在下一节中,我们将更深入地探索 Azure 容器注册中心的一些组件,包括它如何与 Azure Kubernetes 服务集成。
Azure 容器注册表已扩展
虽然 Azure Container Registry (ACR)服务是基于 Docker Registry 开源项目的,但它有许多额外的增强功能值得一提。ACR 利用 Azure Active Directory (Azure AD)支持的基于角色的访问控制(RBAC)来控制对服务上托管的存储库的访问。ACR 已经超越了基本的注册中心,支持作为服务的一部分运行简单或多步任务的能力。由于 ACR 运行在 Azure 中,它与包括 Azure Kubernetes 服务在内的其他 Azure 服务进行了一些定制集成。
安全
有三种不同的 ACR 认证方式:
-
Azure AD 个人登录:登录 ACR 的个人使用他们的 Azure Active Directory 帐户对 ACR 进行身份验证。在要求他们再次进行身份验证之前,会向他们发放一个一小时内有效的令牌。
-
Azure AD 服务主体:类似于个人登录,但是,服务主体可以用于无头认证,并且最常用于自动化平台。
-
管理员帐户:管理员帐户是一个没有链接到 Azure Active Directory 的帐户。admin 帐户拥有在 ACR 注册表上执行任何操作的完全权限。默认情况下,admin 帐户是禁用的,它应该只用于测试和紧急情况。
为了登录到我们在上一节中创建的 ACR,我们可以使用以下命令:
az acr login --name ACR_NAME
由于我们已经登录到 Azure,ACR 获取我们现有的凭证并生成一个令牌供 ACR 使用,这个令牌在一个小时内有效。这段时间过后,令牌过期,必须再次运行az acr login
命令。服务主体登录在登录时使用用户名和密码,因此没有基于缓存凭据颁发的令牌。在自动化流程中使用 ACR 时,服务主体登录是首选的登录类型。
无论是使用个人登录还是服务主体选项,权限都是通过明确定义的角色来分配的。
许可
与 Microsoft Azure 中的许多服务一样,Azure Container Registry 中的权限是使用基于角色的访问控制(RBAC)来分配的。在撰写本文时,该服务定义了七个角色。表 2-1 概述了角色及其权限。
表 2-1
Azure 容器注册的 RBAC
|权限/角色
|
物主
|
捐助者
|
读者
|
广告
|
空气拉力
|
ArcDelete
|
AcrImageSigner
|
| --- | --- | --- | --- | --- | --- | --- | --- |
| 访问资源管理器 | -好的 | -好的 | -好的 | | | | |
| 创建/删除注册表 | -好的 | -好的 | | | | | |
| 推送映像 | -好的 | -好的 | | -好的 | | | |
| 拉映像 | -好的 | -好的 | -好的 | -好的 | -好的 | | |
| 删除映像数据 | -好的 | -好的 | | | | -好的 | |
| 改变策略 | -好的 | -好的 | | | | | |
| 标志映像 | | | | | | | -好的 |
这些角色的分配应遵循最小特权原则,即分配给个人或服务执行特定任务所需的最少权限。AcrPush、AcrPull、AcrDelete 和 AcrImageSigner 角色是专为在其生命周期内执行特定任务的服务和自动化流程而设计的。例如,假设我们使用 Azure Kubernetes 服务来部署存储在 ACR 中的容器。作为 AKS 群集使用的服务主体,AcrPull 角色将授予它足够的权限来访问所需的容器映像,而不授予对资源管理器的访问权限,这是 Reader 角色包含的权限。同样,任何构建新容器映像的 CI/CD 流水线都可以被授予 AcrPush 权限,以便将新映像推送到 ACR。
任务和自动化
除了容器映像的存储,Azure 容器注册服务还包括运行简单和多步骤任务的能力,并在某些操作完成时发出 webhooks。任务和 webhooks 提供了利用 ACR 执行与映像管理相关的常见任务的能力,并有助于集成到 CI/CD 流水线中。
ACR 中的任务可以分为简单任务和多步骤任务,简单任务可以使用az acr build
或az acr task
命令启动,多步骤任务由 YAML 文件定义并通过az acr run
命令提交。
简单的任务
简单的任务用于构建容器映像的新版本。可以使用az acr build
命令手动触发映像的构建。这样做可以将构建容器的负担从本地工作站转移到 ACR,并将生成的映像放在 ACR 中,而不必从本地文件系统推送。使用以下命令从本地 docker 文件创建新映像:
az acr build --registry iaks --image web:v2.
该命令将在容器注册表 iaks 上的映像库 web 中构建一个标记为 v2 的映像。除了从本地工作站卸载构建过程之外,CI/CD 流水线中的服务主体还可以使用相同的命令来自动构建新的容器映像,而无需使用流水线代理计算机上的资源。
它可以由 git 提交或基本映像的更新来触发,而不是手动运行任务。虽然基于 git 提交进行更新的想法具有直观的意义,但是在更新基础映像时更新映像的概念需要一些解释。
ACR 了解存储在其存储库中的映像的映像依赖性。例如,你闪亮的新 web 容器映像可能基于 Docker Hub 的 alpine:stable 映像。当基础映像更新时,您可能希望您的 web 映像也更新,以包含基础映像中的任何更改。ACR 支持创建一个构建任务,如果它检测到存储库中某个映像的基本映像已经更新,就会触发该任务。在这种情况下,命令看起来会像清单 2-13 中的内容。
az acr task create \
--registry iaks \
--name task-web-service \
--image web:v2 \
--arg REGISTRY_NAME=iaks.azurecr.io \
--context https://dev.azure.com/iaks/_git/iaks.git \
--file Dockerfile-web \
--branch master \
--git-access-token $TOKEN
Listing 2-13Creating an ACR task to update an image based on base image updates
Dockerfile-web 文件的定义中引用了 alpine:stable 的基本映像。ACR 反过来创建一个钩子来监听基础映像的变化,如果检测到变化,就会启动一个构建任务。
多步骤任务
ACR 中的多步骤任务建立在现有的简单任务的基础上,同时增加了更多的功能。多步骤任务中的操作包括
-
Build
:构建一个或多个容器映像 -
Push
:将映像推送到私有或公共容器注册表 -
Cmd
:使用与docker run
相似的参数运行容器
作为多步骤任务的一部分而执行的动作在 YAML 格式的文件中定义,该文件使用清单 2-14 中的命令提交给 ACR。
az acr run \
--registry iaks \
-f multi-step-task.yml \
https://dev.azure.com/iaks/iaks.git
Listing 2-14Creating a multi-step task in ACR
该命令指示 ACR 使用在引用的 git 存储库中找到的文件 multi-step-task.yml 在注册表 iaks 上运行任务。
可以在工作流中使用多步骤任务来构建和测试组成基于容器的应用的一组映像,然后在任务中定义的测试通过时更新 Helm 图。虽然这并不能替代全功能 CI/CD 流水线,但它确实提供了一种在代码中定义工作流的方法,并在对 git 存储库进行新的提交时让它们执行。
web 手册
当一个动作在 Azure Container Registry 中完成时,它可以通过 webhook 通知其他服务。这有助于发送简单的通知或启动自动化工作流。触发网络挂钩支持的操作有
-
映像推送
-
映像删除
-
映像隔离
-
Helm 图按钮
-
Helm 图删除
触发 webhook 会向 webhook 配置中定义的服务 URI 发送 POST 请求。POST 请求包括 JavaScript 对象符号(JSON)格式的信息,该信息依赖于触发 webhook 的操作。还可以在 webhook 配置中定义自定义头,随每个 POST 请求一起发送。如果目标服务 URI 需要认证或 POST 有效负载中不包含的一些其他定制数据,则可以利用这些信息。
创建一个 webhook 来联系 Postman echo 服务进行映像推送,如清单 2-15 所示。
az acr webhook create \
--registry iaks \
--name postmanhook \
--actions push \
--uri https://postman-echo.com/post
Listing 2-15Logging into Docker Hub
Postman echo 服务将简单地回复初始 POST 请求的内容,这有助于理解 webhook 发送的信息。
蓝色 Kubernetes 服务集成
Azure Kubernetes 服务(AKS)使用容器映像和 Helm 图将应用部署到 AKS 集群中的节点。方便的是,Azure Container Registry 能够存储这两种资源,并使它们可供 AKS 使用。为了访问存储在 ACR 注册表上的资源,AKS 可以使用 Azure Active Directory 身份验证。
当一个新的 AKS 集群被创建时,它在 Azure Active Directory 中被分配一个服务主体。可以将服务主体的角色分配给 Azure 容器注册中心托管的注册中心,包括 AcrPull 角色。有了这个角色,AKS 集群将能够提取托管在该容器注册表中的容器映像和 Helm 图。
将 ACR 与 AKS 结合使用允许您将映像托管在私有注册表中,并使用本地身份验证服务 Azure AD 为 AKS 集群提供适当的访问级别。您还可以利用 ACR 任务来自动构建、测试和发布基于容器的应用到您的 AKS 集群。
摘要
容器注册中心是在 Kubernetes 上部署应用的关键组件。如果没有映像存储库,就必须将映像手动复制到集群中的每个节点。这不是一个理想的情况。在 Azure Kubernetes Service 中构建和操作应用之前,对容器注册中心及其操作方式有一个适当的了解是很重要的。
在这一章中,你学习了不同类型的容器注册——私有的和公共的。我们讨论了用于与托管在容器注册中心的映像存储库进行交互的命令和工具,包括像推、拉和标记这样的操作。然后,我们研究了 Azure 容器注册服务的特性,以及它如何与 Azure Kubernetes 服务集成。
三、Kubernetes
容器之旅的第一部分是选择容器运行时,了解它的来龙去脉,以及容器化应用。下一个级别是准备在企业级别的生产中运行容器。为了在生产中运行容器,您将需要一个编排平台。
应用的容器化通常包括将应用从整体架构解耦到基于微服务的架构中,组件分散在多个容器中。这导致需要管理数百甚至数千个容器,其中许多共享相同生命周期的容器需要一起管理。
编排平台是管理容器生命周期的解决方案。编排平台控制和自动化动态企业环境中的容器,包括以下功能:
-
供应节点
-
实例化和调度容器
-
容器可用性和冗余
-
跨节点均匀分布容器
-
跨容器的资源分配
-
根据需要扩展集群节点
-
主机和容器运行状况和性能监控
-
根据需要放大或移除容器
-
如果主机上的资源不足,或者主机出现故障,则根据需要在主机之间移动容器
-
跨容器服务发现的负载均衡
-
对容器中运行的服务的外部访问
-
与运行应用的容器相关的应用配置管理
市面上有很多编排平台。进入 Kubernetes,最流行的容器编排平台。Kubernetes 由 Google 创建,旨在在您选择的环境中工作,如裸机服务器、虚拟服务器和公共云上的本地环境。
Kubernetes 已经成为容器编排平台的黄金标准;事实上,三大云提供商 AWS、GCP 和 Azure 也都提供托管的 Kubernetes 服务。Kubernetes 是一个紧密集成的平台,包括托管 Kubernetes 组件、Docker 运行时或莫比运行时,以及提供主机节点和容器的编排。
Kubernetes 的主要特点包括
-
容器的部署和复制
-
缩放容器
-
容器的负载均衡
-
集群中节点的滚动升级
-
故障容器的弹性和自动重新调度
-
容器网络港口对外开放
Kubernetes 的建筑可以看作是复杂的。该架构确实有许多可移动的部分,理解它们很重要。图 3-1 是 Kubernetes 架构的可视化表示。
图 3-1
不可思议的建筑
作为使用 Azure Kubernetes Service (AKS)的先驱,最好对 Kubernetes 有一个扎实的了解。在本章的以下几节中,我们将深入探讨 Kubernetes 的各种组件。
无缝接口
有多种方式与 Kubernetes 交互。Kubernetes 有一个 REST API,您可以使用 REST 调用直接与 API 交互。有一些第三方工具利用这种方法,比如 Rancher 将 Kubernetes 管理引入 Rancher 接口。
第二种最常见的与 Kubernetes 交互的方式是通过 kubectl 命令行接口。在 Kubernetes 中,您几乎可以使用 Kubectl 做任何事情。使用 Kubectl 可以执行的一些任务包括部署 pod、检查和管理集群资源、处理节点、查看日志和升级集群。在第四章“kubectl 概述”中,您将更深入地了解 Kubectl。
除了 Kubectl 命令行界面,Kubernetes 还有一个基于 web 的用户界面,称为 Kubernetes 仪表板。该仪表板可用于 Kubernetes 的基本管理操作。您可以管理诸如 pod、部署、作业、节点、卷、副本集等资源。它还可以用来获取 Kubernetes 资源的状态和健康信息。图 3-2 是 Kubernetes 仪表盘的截图。
图 3-2
Kubernetes 的控制板
Docker 运行时
运行容器需要运行时。Kubernetes 支持 Docker 和 RKT 运行时。正如本书第一章“Docker 容器内部”所述,容器领域中最广泛采用的运行时是 Docker。在 Kubernetes 中,你会发现最常见的运行时是 Docker。使用 Docker,您可以运行基于 Linux 或 Windows 的容器。在 Kubernetes 中运行 Docker 时,也可以运行 Linux 或 Windows 容器。
主节点概述
在 Kubernetes 中,有一个控制和协调集群的主节点。主节点本质上负责管理集群。这个主节点协调集群中发生的任何活动,例如供应节点、节点到节点的通信、充当与 Kubernetes 的接口、调度节点上的容器、维护容器的期望状态以及通过滚动更新工作的应用,等等。以下是构成主节点的组件:
-
Etcd 是一个简单的、分布式的、一致的键值存储。Etcd 存储关于 Kubernetes 集群的数据。它存储数据,如节点、单元、计划作业、服务、API 对象、名称空间和有关集群的其他配置。为了保持安全,只能通过 API 服务器组件访问它。
-
Apiserver 是 Kubernetes 集群所有 REST 请求的中心入口点。REST 请求可用于控制集群,并对组件(如 pod、部署、副本集、服务等)执行操作。Apiserver 还用于与 etcd 通信。
-
Kube-controller-manager 监视 Kubernetes 集群的共享状态,并根据需要进行更改,以确保集群符合所需状态。例如,确保当前正在运行的 pod 数量正确,并且如果 pod 移动,指向 pod 的服务正在运行并跟踪它们。控制器管理器从 Apiserver 获取共享状态。控制器管理器还在后台执行控制器进程的例行任务。
-
除了云控制器管理器处理依赖于底层云提供商的控制器进程之外,云控制器管理器与 Kube 控制器管理器完全一样。例如,如果 Kubernetes 运行在 Azure 上,并且正在利用 Azure 负载均衡器,那么云控制器管理器可以确保所需的负载均衡器正在运行。
-
Kube-scheduler 是处理 Kubernetes 集群中各个节点上的 pod(容器)的所有调度(放置)的组件。调度程序具有关于集群中每个节点的可用资源的信息,因此它可以将 pod 正确地放置在具有可用容量的节点上。
工作节点概述
工作节点是 pod 和应用运行的地方。工作节点是虚拟机。在 Kubernetes 中,您可以拥有 Linux 或 Windows 工作节点。Linux 节点将运行容器和应用,如 Java、Apache Tomcat 和其他基于 Linux 的工作负载。Windows 节点将运行容器和应用,如 IIS、。Net、ASP.net 等等。工作节点包含所有必要的服务,比如运行时、联网、调度、维护容器状态以及与主节点的通信。以下是构成 worker 节点的组件:
-
Docker 是运行容器的运行时引擎。Docker 运行时位于 Kubernetes 集群中的每个节点上。
-
Kubelet 是一种处理与主节点和 etcd 通信的服务。它获取关于新的和现有服务的信息。Kubelet 确保期望的容器是健康和运行的。
-
kube-proxy 充当网络代理和负载均衡器,在 worker 节点上向外界公开服务。它处理 TCP 和 UDP 连接的网络路由。
-
kubectl 是 Kubernetes 命令行接口,与推送到主节点的 Apiserver 交互。
命名空间
名称空间被用来在多个团队之间对 Kubernetes 集群中的资源进行逻辑分段和组织。资源被部署到 Kubernetes 集群的一个名称空间中。这些资源被组合在一起,以便能够作为一个单元进行过滤和控制。
名称空间用于避免冲突。例如,当团队扩展到拥有数千个单元时,部署可能会有相同的名称。在这种情况下,您可以有多个名称空间,其中部署在不同的名称空间中存在重叠的名称,以避免冲突,并简化管理、组织和安全性,如访问策略(RBAC)。有时,名称空间用于生命周期环境,如开发、登台和生产。对于这些环境中的每一个环境,相同的资源可以同时存在于每一个环境中,因为它们在逻辑上是分离的,并且不会相互冲突。
在每个 Kubernetes 集群中,都有一个“默认”名称空间。部署资源时,如果不指定命名空间,它将部署到默认命名空间中。对于 Kubernetes,默认情况下还部署了另外两个名称空间。这些名称空间是 kube-system(用于存储 Kubernetes 组件)和 kube-public(用于存储公共资源,无论是否经过身份验证,所有用户都可以全局读取这些资源)。在 YAML 文件中或者通过使用 Kubectl 命令,很容易创建一个定制的名称空间。下面是执行此操作的语法:
kubectl create namespace namespace1
以下是一个 YAML 文件示例:
kind: Namespace
apiVersion: v1
metadata:
name: namespace1 labels:
name: namespace1
Syntax to apply the YAML file to create the namespace:
kubectl apply -f namespace1.yaml
您可以使用 Kubectl 命令来列出当前的名称空间:
kubectl get namespace
要耗尽命名空间运行:
kubectl delete namespace namespace1
标签和注释
在 Kubernetes 中,当您需要组织、识别和简单地存储关于对象的数据时,标签和注释是帮助您做到这一点的首选功能。如果你曾经使用过像微软 Azure 这样的公共云,你会对这种需求很熟悉,因为你可能使用过标签来帮助组织你的云基础设施。像公共云一样,Kubernetes 在标签和注释方面也有类似的特性。标签和注释将整个标记概念带到了另一个层次。让我们探索标签和注释。
标签是键值对。这些键必须是唯一的。密钥还必须包含 63 个或更少的字符,值必须包含 253 个或更少的字符。标签旨在用于组织、查询和标识一组对象。标签可以在创建时或任何时候贴在对象上:
"metadata": {
"labels": {
"appname" : "webappX",
"environment" : "dev"
}
}
注释也是键值对。与标签相比,注释可以包含更多的字符。注释中的数据是任意的,可以是结构化的或非结构化的,并且能够包括标签中不支持的字符。需要注意的是注释是不能被查询的。注释是在 Kubernetes 中为对象放置元数据的好方法。外部系统和工具可以使用注释数据。下面是一些注释数据的例子:环境,比如 dev、stage、prod、git 分支、pull 请求号、映像信息,比如时间戳或日期、版本信息、应用所有者、部门等等。下面是注释的一个示例:
"metadata": {
"annotations": {
"gitbranch": "brancha",
"department": "marketing"
}
}
综上所述,当您需要查询 Kubernetes 集群中的对象时,请使用标签;当您需要在 Kubernetes 中存储关于对象的一般信息,但不需要查询它,但在外部系统中可能也需要这些信息时,请使用注释。此外,标签应该用于识别对象,当对象上需要非识别数据时,应该使用注释。
Pods
pod 是 Kubernetes 中的一个或多个容器,它们共享资源并耦合在一起。它代表一个部署单元。pod 封装了一个应用,包括容器、存储、网络 IP 以及如何运行容器的配置。把 POD 想象成包裹容器的包装纸。pod 通常部署成两种模式之一:第一种模式是运行单个容器的 pod,第二种模式是运行需要紧密耦合在一起的多个容器的 pod。
单容器 pod 是 Kubernetes 中更常见的用例。多容器 pod 是一种高级场景,用于多个容器组成一个应用,共享相同的生命周期,并需要共享存储和网络等资源。当多个容器属于同一个 pod 时,它们是单个受管实体。调度 pod 时,容器将被放置在同一个节点上,如果 pod 需要移动到另一个节点,所有包含的容器都将被移动。下面是一个 pod 的代码示例:
apiVersion: v1
kind: Pod
metadata:
name: app1-pod
labels:
app: app1
spec:
containers:
- name: app1-container
image: nginx
复制集
副本集定义了一组副本盒。副本集可用于指定需要多少个相同的 pod。例如,如果您想要运行 pod 的四个副本,您可以将其指定为 replicaset 中的副本。Kubernetes 将确保四个 pod 副本一直运行。如果一个 pod 出现故障,将自动部署一个新的 pod,以确保 replicaset 保持运行所需的四个 pod。
注意
本章后面介绍的部署能够管理副本集。副本集通常在部署中定义。建议使用部署集,而不是直接定义副本集。
DaemonSet
DaemonSets 管理复制的 pod 组。它们可用于确保 Kubernetes 集群中的所有节点运行特定 pod 的副本。当您在所有或特定节点上需要一些管理功能时,通常会使用 DaemonSets。何时使用 DaemonSet 的一个例子是,如果您需要使用 fluentd 在所有节点上执行日志收集。另一个例子是当您需要在所有节点上使用一个监控代理时,比如 new relic、AppDynamics、Log Analytics 或 Datadog。
作业
Kubernetes 的工作是监督运行批处理过程的 pod,这些批处理过程在有限的时间内完成。典型的用例或工作是备份、发送电子邮件、代码转换或计算操作。Jobs 支持平行和非平行。
服务
Kubernetes 集群中的服务是定义一组逻辑单元的抽象。服务也是一种机制,用于公开对 pod 或 pod 上运行的应用的外部访问。服务是 pod 顶部的抽象,它提供了一个 IP 地址和 DNS 名称,通过它可以访问 pod。很容易将服务视为指向一个或一组 pod 的指针。当 pod 在 Kubernetes 集群服务中从一个节点移动到另一个节点时,会自动跟踪 pod 所在的位置。有以下三种类型的服务:
-
集群 IP 是部署服务时使用的默认类型。ClusterIP 公开了一个只能在群集内访问的群集内部 IP。
-
节点端口 在节点上的静态端口上公开服务。
-
负载均衡器 配合云提供商使用。负载均衡器使用云提供商负载均衡器对外公开服务。
下面是一个服务代码的示例:
apiVersion: v1
kind: Service
metadata:
name: app1-service
spec:
selector:
app: App1
ports:
- protocol: TCP
port: 80
targetPort: 9523
部署
部署描述了副本集和 pod 的理想状态。部署是清单 yaml 文件。部署控制器通过相应地创建、更新或删除副本集或 pod 来协调 Kubernetes 集群以匹配所需的状态。
配置映射
对于容器化的应用,环境配置应该从应用中抽象出来,并在容器和应用之外处理。这基本上就是容器如何处理配置管理的。将配置与容器和应用分开是使容器可移植的技术之一。配置映射是 Kubernetes 中的一项功能,有助于配置管理。ConfigMaps 保存 pod 中使用的配置数据的键值对。ConfigMaps 在运行时将配置工件绑定到 pod、容器和系统组件。配置工件由命令行参数、配置文件、环境变量和端口号组成。
注意
配置映射应该用于不需要保护的非敏感配置。对于敏感的配置或数据,应该使用 Kubernetes 中的秘密。
ConfigMap 键值数据可以是文字数据,也可以来自文件。配置映射是使用 Kubectl 创建的。以下是创建配置映射的语法:
-
示例 : kubectl 创建配置映射[名称][数据]
-
示例:ku bectl create config map app 1-data-from-file app 1-configs/
kubectl create configmap 用于创建包含键值对的配置映射。和 from-file 指向一个目录。目录中的文件用于填充配置图中的一个键。密钥的名称是文件名。密钥的值来自文件的内容:
- 示例:ku bectl create config map app 1-config-from-literal = app 1-config . app 1 name = myapp 1
创建配置映射后,pod 可以通过 yaml 文件使用它。下面是一个 yamle 文件示例:
apiVersion: v1
kind: Pod
metadata:
name: app1-pod
labels:
app: app1
spec:
containers:
- name: app1-container
image: nginx
env:
- name: app1name
valueFrom:
configMapKeyRef:
name: app1-config
key: app1name
秘密
在 Kubernetes 中,当您需要保护信息时,您可以使用秘密对象。秘密是在 Kubernetes 集群中存储和管理敏感信息的一种方式,比如密码、令牌、SSH 密钥等等。然后,您可以在 pod 或容器映像中引用该秘密,而不是间接地放置密码等秘密。秘密可以从文件或字面上创建。下面是一个使用文字创建秘密的示例:
kubectl create secret generic app1-pass –from- literal=password=PASSWORDHERE
然后在 pod yaml 文件中引用这个秘密。这是一个例子:
env:
– name: APP1_PASSWORD
valueFrom:
secretKeyRef:
name: app1-pass
key: password
建立关系网
与容器联网是复杂的。Kubernetes 的核心是使与容器的联网更容易、更灵活。Kubernetes 在命名、负载均衡、端口分配甚至应用配置方面,将 pods 与网络联系起来,就像它与虚拟机的工作方式一样。Kubernetes 默认使用覆盖网络。Kubernetes 为每个 pod 提供了自己的可路由的唯一 IP 地址和一个 DNS 名称。该 IP 由 pod 中的所有容器共享。
Kubernetes 集群内部的地址空间是扁平的,允许 pods 在没有代理的情况下直接相互通信。pod 也可以跨节点相互通信。Kubernetes 将 iptables 用于 pod 之间的网络连接。可路由的 IP 和 IP 表使您不必像在 Docker 中那样将主机端口映射到容器端口。
当你读到这里的时候,你可能会问自己,“点对点的交流是好的,但是怎样才能把互联网流量从互联网传到点对点呢?”Kubernetes 中的服务将 pod 逻辑地组合在一起,为 pod 上运行的应用提供网络连接。有多种服务类型,可用于将流量路由到 pod。Kubernetes 中存在以下服务类型:
-
节点端口是运行 pod 的节点上的端口映射,允许通过节点 IP 和端口直接访问应用。
-
ClusterIP 是一个内部 IP 地址,在 Kubernetes 集群中用于内部通信。
-
负载均衡器是底层云提供商基于云的负载均衡器,具有外部 IP 地址。负载均衡器后端池已连接到请求的 pod。
-
ExternalName 是访问 pods 上运行的应用的 DNS 条目。
除了前面提到的四种服务类型,还有入口控制器。入口控制器工作在网络 OSI 模型的第 7 层。入口控制器提供可配置的流量路由、TLS 终端和反向代理。入口控制器具有到 Kubernetes 服务的入口规则和路由。入口控制器的一个常见用途是能够从一个公共 IP 地址路由到 Kubernetes 集群中的多个服务。Kubernetes 中最常见的入口控制器是 NGINX 入口控制器。
仓库
容器中的文件是短暂的。当容器重新启动时,文件会丢失。如果需要在容器重启时保留数据,可以使用 Kubernetes 卷。Kubernetes 支持许多类型的卷;但是,最常见的选项是卷或永久卷。对于卷,当容器被销毁时,卷也将不复存在。对于永久卷,当容器被销毁时,数据将继续存在。Kubernetes 中有两种类型的持久卷:第一种是持久卷,第二种是持久卷声明。持久卷是独立于任何 pod 的群集中的资源。为 pod 所在的命名空间中的特定 pod 请求永久卷声明。核心上,卷只是一个包含 pod 中的容器可以访问的数据的目录。以下是 Kubernetes 支持的卷的完整列表:
awsElasticBlockStore
azureDisk
azureFile
cephfs
cinder
configMap
csi
downwardAPI
emptyDir
fc (fibre channel)
flexVolume
flocker
gcePersistentDisk
gitRepo (deprecated)
glusterfs
hostPath
iscsi
local
nfs
persistentVolumeClaim
projected
portworxVolume
quobyte
rbd
scaleIO
secret
storageos
vsphereVolume
在 Kubernetes 中,我们也有一些被称为存储类的东西。存储类与 Kubernetes 中持久存储卷的动态供应一起工作。动态存储配置是指在订购具有预定义类型和配置的存储时,无需了解如何配置物理或云存储设备的详细信息。存储类抽象了特定存储类型的所有细节,然后由开发人员或云提供商使用。存储类别为管理员提供了一种描述他们提供的存储“类别”的方式。类别对应于服务级别和/或备份策略。
摘要
在这一章中,我们向您介绍了 Kubernetes。随着您踏上 Azure Kubernetes 服务之旅,您现在将具备 Kubernetes 及其组件的核心知识。在这一章中,我们探索了 Kubernetes 体系结构,了解了主节点和工作节点以及名称空间、标签、作业、服务和复制集等关键特性。我们还了解了在需要保护信息时使用配置映射和机密进行配置管理。我们了解到 Kubernetes 有一个基于 web 的用户界面,可以用于一些管理任务。最后但同样重要的是,我们探索了 Kubernetes 中网络和存储的工作方式。
四、kubectl
概述
kubectl
是一个命令行界面,用于对 Kubernetes 集群执行命令。您可以使用 kubectl 来部署应用、检查和管理 Kubernetes 集群资源以及检查日志。
在本章中,我们将讨论用于集群操作的各种kubectl
命令。我们将介绍基本命令,并提供如何使用kubectl
进行常见操作的示例,如应用管理、调试和集群管理。本章结束时,您将能够使用kubectl
在 Kubernetes 集群上执行基本操作。
kubectl 简介
当您在kubectl
中执行操作时,它会在$HOME/.kube
目录中查找名为 config 的文件。如果您想使用存储在不同目录中的 kubeconfig 文件,您可以通过设置 KUBECONFIG 环境变量或设置--kubeconfig
标志来实现。
kubeconfig 文件用于组织关于集群、用户、名称空间和认证机制的信息。kubectl
使用 kubeconfig 文件选择集群,并与集群的 API 服务器通信。此外,您还可以定义上下文,以便在集群和名称空间之间快速切换。
在 kubeconfig 文件中,上下文元素用于将访问参数分组到一个方便的名称下。每个上下文有三个参数:集群、名称空间和用户。kubectl
默认情况下,使用当前上下文中的参数与集群通信。
注意
kubectl
默认安装在 Azure 云壳中。有关使用 kubeconfig 文件组织集群访问的完整指南,请参考位于以下 URL 的 Kubernetes 官方文档: kubernetes。io/docs/concepts/configuration/organize-cluster-access-kube config/
。
几乎所有的kubectl
命令通常属于表 4-1 中列出的类别之一。
表 4-1
kubectl 命令类别
|命令类型
|
使用
|
描述
|
| --- | --- | --- |
| 声明性资源管理 | 开发和运营 | 用于以声明方式使用资源配置管理 Kubernetes 工作负载。 |
| 必要的资源管理 | 仅开发 | 使用这些命令通过命令行参数和标志来管理 Kubernetes 工作负载。 |
| 打印工作负荷状态 | 排除故障 | 包括用于以下操作的命令:打印资源的汇总状态和信息、打印资源的完整状态和信息、打印资源的特定字段以及查询与标签匹配的资源。 |
| 与容器交互 | 排除故障 | 用于调试 Exec、Attach、Cp 和 Logs 等操作,包括用于打印容器日志、打印群集事件、执行或附加到容器以及将文件从群集中的容器复制到用户文件系统等操作的命令。 |
| 集群管理 | 排除故障 | 用户需要在集群节点上执行操作,kubectl 支持 drain 和 cordon 节点等集群操作的命令。 |
注意
kubectl
默认安装在 Azure 云壳中。要在本地安装kubectl
,请在 Azure CLI 中执行az aks install-cli
命令。
Kubernetes 基础
本节提供了基本 kubectl 命令的高级概述。在整本书中,您会注意到使用中的各种 kubectl 命令。在本节中,我们将只介绍最常用的命令。本节中展示的例子涉及到在 Kubernetes 中部署一个简单的 ngnix 集群。
立方结构语法
以下是从终端运行 kubectl 命令的语法:
-
命令:这指定了用户想要对资源执行的操作,比如创建、获取和删除。
-
类型:这表示资源。请记住,资源类型不区分大小写,您可以使用单数、复数或缩写形式来引用资源类型。
-
名称:这表示资源名称。资源名称区分大小写。如果不提供名称,将显示所有资源的详细信息。
-
标志:标志是可选的。例如,您可以利用
-s
或--server
标志来指定 Kubernetes API 服务器的地址和端口。
kubectl [command] [TYPE] [NAME] [flags]
注意
要获得使用 kubectl 可以执行的操作的完整参考,请访问 kubectl reference,网址为 kubernetes。io/docs/reference/kube CTL/kube CTL/
。
您可以通过在终端中运行kubectl api-resources
来列出所有支持的资源类型及其别名。
在 kubectl 中格式化输出
任何 kubectl 命令的默认输出都是纯文本。为了生成特定格式的输出,可以使用-o
或--output
标志。以下是您需要使用的语法:
kubectl [command] [TYPE] [NAME] -o <output_format>
表 4-2 列出了根据您执行的kubectl
操作支持的输出格式。
表 4-2
立方结构输出格式
|输出格式
|
描述
|
| --- | --- |
| -o 自定义列= | 使用逗号分隔的自定义列列表显示表格。 |
| -o custom-columns-file=
| -哦,我的上帝 | 打印 JSON 格式的 API 对象。 |
| -jsonpath = |
五、部署 Azure Kubernetes 服务
Azure Kubernetes Service (AKS)通过提供托管的 Kubernetes 即服务平台,简化了 Kubernetes 集群的部署。通过将健康监控和维护以及主节点管理等日常任务卸载到 Azure 平台,降低了管理 Kubernetes 的操作复杂性。
在本章中,我们将探讨如何使用 Azure 门户、Azure CLI、Azure 资源管理器(ARM)模板和 Terraform 部署 AKS 集群。我们将回顾每个部署选项的流程,然后解释其他功能配置,如高级网络、Azure Active Directory 集成和监控。在本章结束时,您将对 AKS 部署过程、选项和步骤有一个很好的了解。
Azure Kubernetes 服务部署概述
您可以使用几种方法部署 AKS 集群。每种方法都有自己的优点,选择如何部署 AKS 集群取决于您的偏好和场景。但是,您必须提供一些在所有这些方法中部署 AKS 集群所需的强制参数。我们将在接下来的章节中讨论这些参数是什么。
通过 Azure 门户进行部署
使用 Azure 门户创建 AKS 集群是一个简单的过程。下面解释了这样做的过程。
在 Azure Marketplace 中,选择 +创建资源 ➤ 容器 ➤ Kubernetes 服务。在创建 Kubernetes 集群页面中,配置以下选项:
-
在基础部分,需要配置以下选项:
-
项目细节:在这个部分中,选择您需要创建 AKS 集群的 Azure 订阅。
-
集群细节:为 AKS 集群选择或创建一个 Azure 资源组,为 Kubernetes 集群名称提供一个值,为部署 AKS 集群提供一个 Azure 区域,选择想要的 Kubernetes 版本,最后为 AKS 集群提供一个 DNS 名称前缀。
-
主节点池:在这个部分,您需要从 Azure VM SKUs 中为 AKS 节点选择一个 VM 大小。请记住,一旦创建了 AKS 集群,就不能更改虚拟机的大小。选择虚拟机大小和节点计数。您可以从将节点计数设置为 1 开始。
-
Click Next: Scale ➤.
图 5-1
创建一个 Kubernetes 集群基础部分
-
-
在刻度部分保留默认选项;之后,点击下一步:认证 ➤.
注意我们将在第七章“运营 Azure Kubernetes 服务”中详细讨论 AKS 的扩展选项
-
在认证部分:
-
您可以通过保持服务主体字段不变来创建新的服务主体,或者选择配置服务主体来使用现有的服务主体。请记住,如果您选择使用现有的,您将必须在下一个弹出的刀片中提供服务主体名称(SPN)客户端 ID 和机密。
-
启用 RBAC :将该选项设置为是以允许 Kubernetes 基于角色的访问控制(RBAC),该控制对访问 AKS 集群资源提供更细粒度的控制
-
Click Next: Networking ➤.
图 5-2
创建一个 Kubernetes 集群验证部分
-
-
Leave the Network configuration radio button to Basic settings under the Networking section to use kubenet with a default VNet configuration. Selecting Advanced will redirect you to configure the following which allows you to use an Azure CNI with further options to customize your VNet. Click Next: Monitoring ➤.
图 5-3
创建一个 Kubernetes 集群网络部分
-
Under Monitoring section, leave the Enable container monitoring option to Yes. Here you can either create a new Log Analytics workspace for your new AKS cluster or create a new one. Once done, click the Review + Create button at the bottom of the screen. Once the validation is completed, click Create.
图 5-4
创建一个 Kubernetes 集群验证部分
创建 AKS 群集的过程需要几分钟时间来完成部署。部署完成后,您可以通过点击下的转到资源下的【后续步骤】或通过在屏幕顶部的搜索栏中搜索资源组名称或 AKS 集群名称来访问其仪表板,从而查看 AKS 集群的状态。
图 5-5
AKS 集群仪表板
通过 Azure CLI 部署
Azure CLI 是用于管理 Azure 资源的命令行工具。它被设计成一个跨平台的工具,可以部署在 Windows、Linux 或 MacOS 系统上。为了提供更好的 Azure CLI 体验,Azure 门户提供了 Azure Cloud Shell ,这是一个交互式 Shell 环境,您可以通过浏览器使用它。使用 Azure Cloud Shell 的优势在于,您可以将它与预安装的 bash 或 PowerShell Azure CLI 命令一起使用,而无需在本地计算机上安装任何东西。
注意
为了尝试本节中的说明,您可以选择使用安装在本地计算机上的 Azure CLI 或利用 Azure Cloud Shell。
-
Launch an Azure Cloud Shell session by clicking the Cloud Shell button on the top-right menu bar in the Azure Portal.
图 5-6
推出 Azure 云壳
-
通过输入以下 Azure CLI 命令,创建一个资源组来部署您的 AKS 群集。
az group create --name jcbaksrg01 --location eastus
Listing 5-1Create a resource group for the AKS cluster
如果资源组创建成功,您应该会看到以下输出。
- 使用
az aks create
命令创建 AKS 集群。下面的示例创建了一个名为 jcbaksclu02 的集群,该集群有一个节点,--enable-addons monitoring
参数将为该集群启用 Azure Monitor for containers。几分钟后,一旦集群创建完成,Azure CLI 将在 Azure Cloud Shell 窗口中返回 JSON 格式的集群信息。
{
"id": "/subscriptions/<guid>/jcbaskrg01",
"location": "eastus",
"managedBy": null,
"name": "jcbaskrg02",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}
Listing 5-2Create a resource group output
az aks create --resource-group jcbaksrg01 --name jcbaksclu01 --node-count 1 --enable-addons monitoring --generate-ssh-keys
Listing 5-3Create an AKS cluster
通过 Azure 资源管理器模板进行部署
Azure 资源管理器(ARM)模板引入了基础设施作为 Azure 部署的代码功能。ARM 模板是定义 Azure 部署的基础设施和配置的 JavaScript 对象符号(JSON)文件。ARM 模板使用声明性语法,您可以通过使用 ARM 模板指定要部署的资源及其各自的配置。
在使用 ARM 模板创建 AKS 集群之前,您需要首先提供一个 SSH 公钥和 Azure Active Directory 服务主体。
创建一个 SSH 密钥对
连接和访问 AKS 节点需要 SSH 密钥对。根据下面的例子,通过在 Azure Cloud Shell 会话中执行ssh-keygen
命令,您将在~/中生成一个带有 2048 位长度的 RSA 加密的 SSH 公共和私有密钥对。Azure 云外壳文件存储中的 ssh 目录。
ssh-keygen -t rsa -b 2048
Listing 5-4Create an SSH key pair in Azure Cloud Shell
创建服务主体
Azure Active Directory 服务主体名称(SPN)是允许 AKS 群集与 Azure 环境中的其他 Azure 资源进行交互所必需的。通过执行az ad sp create-for-rbac
CLI 命令,您可以为这个练习创建必要的服务主体。--skip-assignment
参数防止分配任何额外的权限。默认情况下,此服务主体仅在一年内有效。
az ad sp create-for-rbac --skip-assignment
Listing 5-5Create a service principal in Azure Cloud Shell
从生成的输出中记下 appId 和密码的值。这些是在 ARM 模板中填充参数所必需的。
{
"appId": "141b2bef-9350-4e80-a0fa-a6aa456750a9",
"displayName": "azure-cli-2019-09-30-01-39-37",
"name": "http://azure-cli-2019-09-30-01-39-37",
"password": "182bb4e7-b53f-4cc4-811d-c72ba828a75d",
"tenant": "<tenant id>"
}
Listing 5-6JSON output of the create service principal operation
使用 Azure 资源管理器快速入门模板
如果你不是 ARM 模板方面的专家,你总是可以利用 Azure Resource Manager QuickStart 模板来开始。
注意
在这个例子中,我们将使用 101-aks 快速入门模板来解释使用 Azure 资源管理器模板部署 aks 集群的过程。有关更多示例,请访问以下 URL:
https://azure.microsoft.com/en-au/resources/templates/?term=Azure%20Kubernetes%20Service
-
导航到以下 URL 以打开 101-aks 快速入门模板,然后单击部署到 Azure :
https://azure.microsoft.com/en-au/resources/templates/101-aks/
图 5-7
Azure 快速入门模板 101-aks
-
在模板中输入和/或配置以下值:
-
订阅:选择想要部署 AKS 集群的 Azure 订阅。
-
资源组:您可以选择一个已有的资源组,也可以选择新建提供一个唯一的名称来创建一个新的资源组,点击确定。
-
位置:为你的 AKS 集群选择 Azure 区域。
-
集群名称:为 AKS 集群提供一个唯一的名称。
-
DNS 前缀:为您的集群提供一个唯一的 DNS 前缀。
-
Linux 管理员用户名:提供使用 SSH 连接的用户名。
-
SSH RSA 公钥:输入您的 SSH 密钥对的公共部分(默认为的内容)~/。ssh/id_rsa.pub 。
-
服务主体客户端 ID :提供上一节生成的 appId 值。
-
服务主客户端秘密:提供前面生成的密码。
-
Click the I agree to the terms and conditions stated above: checkbox to agree to the terms and conditions.
![img/484429_1_En_5_Fig8_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_5_Fig8_HTML.jpg) 图 5-8 101-aks 快速入门模板的部署屏幕
-
-
点击购买。您的 AKS 集群部署将需要几分钟才能完成。
注意
您可以使用编辑模板或编辑参数按钮定制手臂模板或编辑快速入门模板中提供的参数。
通过地形部署
Terraform 是一个基础设施即代码(IaC)工具,旨在安全高效地构建、更改和版本化基础设施。terra form 中的配置文件定义了运行应用所需的组件。在 Terraform 中生成一个执行计划来描述达到所需配置状态的指令,然后执行它来构建所描述的基础设施。如果配置发生变化,Terraform 能够确定变化并创建增量执行计划,然后应用这些计划。
使用 Terraform 创建 AKS 集群的步骤在( https://docs.microsoft.com/en-us/azure/terraform/terraform-create-k8s-cluster-with-tf-and-aks
)中有很好的记录。
注意
Terraform 默认预装在 Azure 云壳中。如果您需要在本地设置 Terraform 以遵循前一篇文章中的说明,请参考以下 URL:
连接到您的 AKS 集群
您可以使用 Kubernetes 命令行客户端kubectl
来管理您的 AKS 集群。如果你使用的是 Azure 云壳,那么kubectl
是预装的。如果你想在你的本地计算机(已经安装了 Azure CLI 的地方)上本地安装kubectl
,你可以使用下面的命令。
az aks install-cli
Listing 5-7Installing kubectl on a local installation of Azure CLI
通过使用az aks get-credentials
命令,您可以配置 kubectl 来连接到您的 Kubernetes 集群。这会下载所需的凭证并配置 Kubernetes CLI 来使用它们。
az aks get-credentials --resource-group jcbaksrg01 --name jcbaksclu01
Listing 5-8az aks get-credentials command
然后,您可以执行kubectl get
命令来验证到您的集群的连接,并查看它是否返回集群节点列表。
kubectl get nodes
Listing 5-9kubectl get command
以下是示例输出,显示了通过前面的方法创建的 Kubernetes 集群 jcbaksclu01 中的节点。在将任何应用部署到 AKS 集群之前,所有节点的状态都应该是就绪。
NAME STATUS ROLES AGE VERSION
aks-agentpool-26412741-0 Ready agent 120m v1.13.10
Listing 5-10kubectl get command output for jcbaksclu01
摘要
您可以使用几种方法部署 Azure Kubernetes 服务。正如本章前面所解释的,由您来决定哪种方法适合您的部署需求。本章介绍了如何部署 AKS 和配置启动和运行 AKS 集群所需的基本参数。
在本章中,你学习了如何使用四种不同的方法创建 AKS 集群,通过 Azure 门户、Azure CLI(通过本地安装的实例或通过 Azure 云外壳)、Azure 资源管理器模板,以及最后一个非常流行的第三方基础设施即代码工具“Terraform”我们回顾了使用上述每种方法对您的 AK 进行初始配置的过程。最后,我们简要讨论了如何使用 Kubernetes 的命令行工具kubectl
连接到 AKS 集群。
六、通过 Azure Kubernetes 服务部署和使用 Rancher
随着您继续进入容器世界,您将到达临界质量点。将需要运行一个编排平台来处理容器的生命周期。在第三章“Kubernetes 内部”,我们进入了 Kubernetes,最常见的编排平台。在第五章中,“部署 Azure Kubernetes 服务”,我们介绍了如何部署 Azure Kubernetes 服务(AKS)。Kubernetes 对于刚开始使用容器编排平台的人来说可能很复杂。
微软的托管 Kubernetes 服务 AKS 消除了运行 Kubernetes 集群的一些复杂性;然而,运行 Kubernetes 集群仍然是一个挑战,包括随之而来的所有事情,例如操作多个 Kubernetes 集群、在集群中扩展、联网、RBAC、监控、通过 HELM charts 部署捆绑解决方案(将在后面的章节中介绍)等等。市场上有第三方解决方案可以降低运行 Kubernetes 的复杂性。牧场主是这个解决方案之一,如果不是最好的。
在这一章,我们将给出一个 Rancher 的概述,也将探讨 Rancher 如何与 AK 一起使用。
什么是牧场主?
简而言之,Rancher 是一个开源解决方案,可以用来部署和操作一个或多个 Kubernetes 集群。Rancher 可以跨内部或云提供商(如 AWS、GCP、数字海洋和 Azure)部署和管理 Kubernetes 集群。它可以用于在您自己的基础设施上部署和管理您自己的 Kubernetes 集群,甚至是来自云提供商的托管集群服务,例如 Azure Kubernetes 服务。
不像市场上的其他开源解决方案,Rancher 是完全免费的。它没有需要付费的社区版和企业版。使用 Rancher,您可以在部署时获得所有功能。牧场主在经济上支持自己的方式是通过为生产牧场主的组织设计的有偿支持选项。
因为 Rancher 几乎可以在任何地方操作 Kubernetes 集群,所以它还可以用来在提供者之间迁移资源。
Rancher 总体上有助于简化 Kubernetes 的管理。它简化管理的一些方法是集中身份验证和访问控制,通过 Prometheus 和 Grafana 引入开箱即用的监控,拥有自己的应用库,以及 HELM charts 和简化的 Kubernetes 版本升级。
虽然 Rancher 抽象了管理 Kubernetes 集群的大部分复杂性,但如果需要,它也允许高级管理。例如,Kubernetes 管理员可以通过 Rancher 门户访问 kubectl。
为什么使用牧场主与库伯内特?
当有人了解 Rancher 时,最常见的问题之一是:“为什么我应该将 Rancher 与 Kubernetes 一起使用,而不是单独使用 Kubernetes?”这个问题的答案是有很多理由使用牧场主与库伯内特;但是,在某些情况下,使用 Rancher 可能没有意义。这里我们将看看使用 Rancher 的理由。让我们浏览一下:
-
Kubernetes 集群的部署和升级:通过 Rancher 部署和升级 Kubernetes 集群是一个简化且无缝的过程。
-
用户界面和 API:Rancher 为使用 Kubernetes 的用户提供了一个简化的用户界面。Rancher 还提供了一个接口 API。
-
集中管理多个 Kubernetes 集群:许多组织正在采用多种云方法,因此他们可能会跨多个云提供商运行一个 Kubernetes 集群。当 Kubernetes 集群跨云提供商甚至在本地部署时,可以使用 Rancher 从一个地方集中管理所有集群。Rancher 集中管理 RBAC、安全策略管理、容量管理、委托管理、集群备份和恢复、日志记录和监控等。
-
集中和简化 Kubernetes 的 RBAC:Kubernetes 的授权和访问可以从 Rancher 轻松管理。
-
Rancher 和 Prometheus 和 Grafana 一起从箱子里出来:监控 Kubernetes 是至关重要的。Prometheus 和 Grafana 是常见的监控和可视化工具。由于这些解决方案与 Rancher 打包在一起,可以随时监控 Kubernetes,因此减少了部署这些解决方案并准备好监控 Kubernetes 的工作负载。
-
Rancher 简化 Helm 图 : Rancher 允许你加载 Helm 图库和/或 Rancher 库。这些库使得轻松地部署应用成为可能。
-
Kubernetes 采用:通过降低 Kubernetes 的学习曲线,让程序员专注于开发应用而不是运行应用,来推动 Kubernetes 的采用。
从前面的列表中可以看出,将 Rancher 与 Kubernetes 结合使用有很多价值。接下来,让我们看看如何部署 Rancher 并将其与 AKS 一起使用。
如何在 Azure 上部署 Rancher
Rancher 作为 Docker 顶部的容器运行。您可以在本地或云提供商上部署 Rancher。在这一节中,我们将在一个运行 Docker 的 Ubuntu 服务器上部署 Rancher。
我们将使用 Azure ARM 模板部署这个 VM 和 Rancher。我们将使用的 ARM 模板使用 Docker 和最新版本的 Rancher 作为容器来部署 Ubuntu VM。Rancher 容器从 Docker Hub 上的( https://hub.docker.com/r/rancher/rancher
)部署。这确保了总是部署最新的 Rancher 版本。
我们将使用的 ARM 模板名为 RancherNode.JSON。下面是 ARM 模板代码:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"type": "string",
"metadata": {
"description": "Username for the Rancher Node Virtual Machine."
}
},
"adminPassword": {
"type": "securestring",
"metadata": {
"description": "Password for the Rancher Node Virtual Machine."
}
},
"dnsNameForPublicIP": {
"type": "string",
"metadata": {
"description": "Unique DNS Name for the Public IP used to access the Rancher Portal."
}
},
"vmSize": {
"type": "string",
"defaultValue": "Standard_F1",
"metadata": {
"description": "VM size for the Rancher Node."
}
},
"ubuntuOSVersion": {
"type": "string",
"defaultValue": "14.04.4-LTS",
"metadata": {
"description": "The Ubuntu version for deploying the Docker containers. This will pick a fully patched image of this given Ubuntu version. Allowed values: 14.04.4-LTS, 15.10, 16.04.0-LTS"
},
"allowedValues": [
"14.04.4-LTS",
"15.10",
"16.04.0-LTS"
]
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
},
"variables": {
"imagePublisher": "Canonical",
"imageOffer": "UbuntuServer",
"nicName": "RancherNodeNic",
"extensionName": "DockerExtension",
"addressPrefix": "10.0.0.0/16",
"subnetName": "RancherSubnet",
"subnetPrefix": "10.0.0.0/24",
"diskStorageType": "Standard_LRS",
"publicIPAddressName": "RancherNodePublicIP",
"publicIPAddressType": "Dynamic",
"vmName": "RancherNode",
"virtualNetworkName": "RancherVNet",
"subnetRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]"
},
"resources": [
{
"apiVersion": "2017-04-01",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[parameters('location')]",
"properties": {
"publicIPAllocationMethod": "[variables('publicIPAddressType')]",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsNameForPublicIP')]"
}
}
},
{
"apiVersion": "2017-04-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "[variables('virtualNetworkName')]",
"location": "[parameters('location')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[variables('addressPrefix')]"
]
},
"subnets": [
{
"name": "[variables('subnetName')]",
"properties": {
"addressPrefix": "[variables('subnetPrefix')]"
}
}
]
}
},
{
"apiVersion": "2017-04-01",
"type": "Microsoft.Network/networkInterfaces",
"name": "[variables('nicName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
"[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
},
"subnet": {
"id": "[variables('subnetRef')]"
}
}
}
]
}
},
{
"apiVersion": "2017-03-30",
"type": "Microsoft.Compute/virtualMachines",
"name": "[variables('vmName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSize')]"
},
"osProfile": {
"computerName": "[variables('vmName')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('imagePublisher')]",
"offer": "[variables('imageOffer')]",
"sku": "[parameters('ubuntuOSVersion')]",
"version": "latest"
},
"osDisk": {
"name": "[concat(variables('vmName'),'_OSDisk')]",
"caching": "ReadWrite",
"createOption": "FromImage",
"managedDisk": {
"storageAccountType": "[variables('diskStorageType')]"
}
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
}
]
}
}
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(variables('vmName'),'/', variables('extensionName'))]",
"apiVersion": "2017-03-30",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]"
],
"properties": {
"publisher": "Microsoft.Azure.Extensions",
"type": "DockerExtension",
"typeHandlerVersion": "1.0",
"autoUpgradeMinorVersion": true,
"settings": {
"compose": {
"rancher": {
"image": "rancher/rancher:stable",
"ports": [
"80:80",
"443:443"
],
"volumes": [
"/opt/rancher:/var/lib/rancher"
]
}
}
}
}
}
]
}
这个 ARM 模板也可以在这里下载: https://github.com/Buchatech/DeployRanchertoAzure
。
使用您选择的部署选项部署 ARM 模板。您需要提供以下参数的数据:
-
签署
-
资源组
-
位置
-
管理员用户名
-
管理员密码
-
公共 IP 的 Dns 名称
-
虚拟机大小
-
Ubuntu OS 版本
部署 Ubuntu VM 后,您应该会看到新资源组中的资源,如表 6-1 所示。
表 6-1
资源组中蓝色资源上的牧场主
|名字
|
类型
|
| --- | --- |
| 兰彻网 | 虚拟网络 |
| 牧场主 | 虚拟计算机 |
| 兰彻诺尔德 PublicIP | 公共 IP 地址 |
| 蓝丘杜鹃 | 网络接口 |
| 兰彻罗德 _OSDisk | 唱片 |
为了完成 Rancher 部署,您需要通过 Rancher 门户完成设置。URL 是我们部署的 Rancher 节点 VM 的 DNS 名称。您可以通过在概述页面上的 Azure 门户中单击 Rancher 节点 VM 来找到 DNS 名称。以下是 URL 的一个示例:
https://NAMEOFTHEVM.centralus.cloudapp.azure.com
牧场主门户网站会提示您设置密码。如图 6-1 所示。
图 6-1
牧场主设置密码
设置密码后,Rancher 门户会提示您输入正确的 Rancher 服务器 URL。这将自动成为如图 6-2 所示的牧场主节点虚拟机 DNS 名称。单击保存 URL。
图 6-2
蓝丘保存 URL
然后,您将直接登录到 Rancher 门户的“您将看到集群”页面。这就完成了在 Azure 上部署 Rancher 的部署。接下来,我们将探索部署一个新的 AKS 集群,并从 Rancher 内部连接到一个现有的 AKS 集群。
使用 Azure Active Directory 对牧场主进行身份验证
您将需要从 Rancher 到 Azure working 的认证,然后才能部署或管理现有的 AKS 集群。为了从 Rancher 向 Azure 进行身份验证,您将需要 Azure Active Directory 中的服务主体名称(SPN)对象。这将用于 Azure 的身份验证。
要创建这个 SPN,您只需要运行一行语法。建议您在 Azure Cloud Shell 中从 Bash 运行这个。
注意
使用以下步骤在 Azure Cloud Shell 中打开 Bash:
登录 Azure 门户网站。
通过点击➤.从顶部导航启动云壳
如果这是您第一次运行云外壳,请选择订阅以创建存储帐户和 Microsoft Azure 文件共享。
当 Cloud Shell 在 Azure 门户底部启动时,确保 Shell 窗口左侧的环境下拉菜单显示的是 Bash 而不是 PowerShell。
占位符文本。稍后在能够清理便笺格式时删除。
注意
您将需要想要在其中创建 AKS 集群的订阅的订阅 ID。您可以在 Cloud Shell 中运行以下语法来获取您登录的帐户的订阅列表。这将列出包括 id 在内的订阅属性信息。复制订阅 ID 以备后用。
az account list
使用以下语法创建具有特定名称的 SPN,并将参与者角色分配给指定的订阅:
az ad sp create-for-rbac --name NAMEOFTHESPNHERE --role contributor --scopes /subscriptions/SUBSCRIPTIONIDHERE
例如:
az ad sp create-for-rbac --name rancherSPN --role contributor --scopes /subscriptions/148727f76-9q1b-4941-coa6-92c5d153fe73
输出将类似于:
将“rancherSPN”更改为“ http://rancherSPN
”的有效 URI,这是用于服务主体名称的必需格式
Retrying role assignment creation: 1/36
{
"appId": "012d8611-c9a3-4e90-80d9-ad6504c823g8",
"displayName": " rancherSPN ",
"name": "http:// rancherSPN",
"password": "6a4b83fc-31qa-40f0-c4c6-rba8c5av460b",
"tenant": "0pw0cc24-q010-4f7b-h08e-9o57a72t531d"
}
请记住将这些信息复制到某个地方,因为在创建 AKS 集群时,您将需要这些信息从 Rancher 连接到 Azure。
注意
appId 将用于 Rancher 中的 clientId 字段。
就是这样!这就是创建 SPN 并从 Rancher 获得向 Azure 认证所需的信息所要做的全部工作。在下一节中,我们将从 Rancher 创建一个新的 AKS 集群。
与牧场主一起部署 AK 步枪
此时,我们已经在 Azure 上部署了 Rancher。现在让我们看看使用 Rancher 部署新的 AKS 集群的过程。使用以下步骤在 Azure 中从 Rancher 部署新的 AKS。
注意
在下面的步骤中,我们将调用所需的设置,如 DNS 前缀,但不调用可选设置,如 Azure 标记或高级网络。在部署 AKS 集群时,您可以根据需要配置可选设置。
在 Rancher 门户中,单击顶部导航菜单中的集群。
点击添加集群,选择 Azure AKS,如图 6-3 所示。
图 6-3
Azure AKS 托管 Kubernetes 提供商
您将看到如图 6-4 所示的账户访问设置。
图 6-4
帐户访问设置
输入一个集群名称,如图 6-5 所示。
图 6-5
牧场主群集名称
创建 SPN 后,将您从上一部分复制的信息输入到帐户访问设置中。
单击下一步:验证和配置节点。
接下来,在集群选项下,给你的集群一个 DNS 前缀,如图 6-6 所示。
图 6-6
群集 DNS 前缀
在节点下,在集群资源组字段中输入资源组的名称,如图 6-7 所示。
图 6-7
集群资源组和 SSH 密钥
此外,在 Nodes 下,输入 SSH 公钥并单击 Create。
注意
PuTTY Key Generator 是一个免费的工具,可以用来生成一个新的 SSH 密钥。你可以在这里下载: www.puttygen.com
。
AKS 集群将开始供应,如图 6-8 所示。
图 6-8
AKS 集群配置
部署 AKS 集群后,它将在 Rancher 门户中显示为活动的。AKS 集群现已部署,您可以访问 Azure 门户,导航到它创建的资源组,并查看部署的资源管理器,包括 AKS 集群、日志分析工作区和 Containers Insights 解决方案,如图 6-9 所示。
图 6-9
Azure 上的 AKS 集群资源
回到 Rancher 门户,您现在可以单击 AKS 集群来访问仪表板、监控和集群设置,从 Rancher 或 Helm 目录安装应用,启动 Kubectl 等。图 6-10 是 Rancher 中 AKS 集群的仪表板示例。
图 6-10
牧场主的 AKS 集群仪表板
下面两个屏幕截图展示了 Rancher 中针对 AKS 集群的 Grafana 监控。图 6-11 显示了实时集群指标。
图 6-11
牧场主的 Grafana 聚类度量
图 6-12 显示了集群和 Kubernetes 组件的实时指标。
图 6-12
Grafana Kubernetes 牧场主的组件度量
您还可以访问完整的 Grafana UI 和系统,以更深入地了解您的 AKS 集群及其资源,如图 6-13 所示的节点和单元。
图 6-13
格拉凡·ui
摘要
这就把我们带到了本章的结尾。Rancher 不像 Docker 和 Kubernetes 那样出名。然而,正如您在本章中了解到的,Rancher 是简化 Kubernetes 生命周期的一个有用的解决方案。具体来说,在这一章中,我们介绍了什么是 Rancher,为什么您将它与 Kubernetes 一起使用,在 Azure 上部署 Rancher,最后将 Rancher 连接到 Azure,以便您可以部署新的 AKS 集群。
七、操作 Azure Kubenetes 服务
一旦您部署了第一个 AKS 集群,了解如何配置、监控和管理 AKS 环境是非常重要的。将应用部署到 AKS 集群时,AKS 操作员的角色至关重要,因为集群优化是 AKS 中的关键操作流程。
在本章中,我们将从集群操作者的角度探讨如何操作 AKS 集群。我们将回顾处理集群操作的流程,如何为 AKS 配置数据存储,以及 AKS 中的网络、安全和身份验证如何工作。然后,我们将使用 Azure Monitor for containers 深入 AKS 监控领域。最后,我们将介绍 Azure Kubernetes 服务的业务连续性和灾难恢复(DR)规划流程和最佳实践。本章结束时,您将从 AKS 操作员的配置、监控和管理角度全面了解 AKS 集群的操作。
Azure Kubernetes 服务中的集群操作
在操作 Azure Kubernetes 服务集群时,熟悉集群常见操作非常重要。以下部分概述了您在使用 AKS 时会遇到的一些常见集群操作。
注意
下面几节中的解释是在 Azure Cloud Shell 中执行的。如果您使用本地安装,请通过执行az –version
确保您运行的是 Azure CLI 版本 2.0.65 或更高版本。
手动扩展 AKS 集群节点
应用的资源需求确实会随时间而变化。在这种情况下,您可以手动或自动扩展 AKS 集群,以增加或减少节点数量。在缩减规模操作中,您的 AKS 节点被小心地封锁和排空,以最大限度地减少应用中断。在向上扩展操作中,在工作节点被标记为就绪之前,AKS 会一直等待,然后才会在其上调度 pod。
以下示例首先获取 jcbaksrg01 资源组中 jcbaksclu01 群集的节点池名称。
az aks show --resource-group jcbaksrg01 --name jcbaksclu01 --query agentPoolProfiles
Listing 7-1az aks show command
您可以在下面的输出中看到名称是 nodepool1。
{
"count": 1,
"maxPods": 110,
"name": "nodepool1",
"osDiskSizeGb": 30,
"osType": "Linux",
"storageProfile": "ManagedDisks",
"vmSize": "Standard_DS2_v2"
}
]
Listing 7-2az aks show command output
然后,您可以使用az aks scale command
来扩展集群节点。以下示例将 jcbaksclu01 的节点计数从 1 调整到 3。
az aks scale --resource-group jcbaksrg01 --name jcbaksclu01 --node-count 3 --nodepool-name nodepool1
Listing 7-3az aks scale command
您应该会看到以下类似的输出,显示集群已成功扩展到三个节点,如 agentPoolProfiles 部分所示:
{
"aadProfile": null,
"addonProfiles": null,
"agentPoolProfiles": [
{
"count": 3,
"maxPods": 110,
"name": "nodepool1",
"osDiskSizeGb": 30,
"osType": "Linux",
"storageProfile": "ManagedDisks",
"vmSize": "Standard_DS2_v2",
"vnetSubnetId": null
}
],
[...]
}
升级 AKS 集群
在 AKS 集群的生命周期中,您需要将其升级到最新的或者特定的 Kubernetes 版本。以下示例说明了如何升级 AKS 集群中单个默认节点池的主组件。
首先,通过对集群执行如下的az aks get-upgrades
命令,检查集群是否有新的 Kubernetes 版本。
az aks get-upgrades --resource-group jcbaksrg01 --name jcbaksclu01 --output table
Listing 7-4az aks get-upgrades command
如果有任何可用的升级,您应该会看到类似下面的输出。在本例中,您的集群可以升级到 Kubernetes 版本 1.14.5 和 1.14.6。
Name ResourceGroup MasterVersion NodePoolVersion Upgrades
------- --------------- --------------- ----------------- --------------
default jcbaksrg01 1.13.10 1.13.10 1.14.5, 1.14.6
Listing 7-5az aks get-upgrades command output
如果没有可用的升级,您应该会看到以下错误消息作为输出。
ERROR: Table output unavailable. Use the --query option to specify an appropriate query. Use --debug for more info.
Listing 7-6No upgrades available error
注意
升级 AKS 集群时,不能跳过 Kubernetes 次要版本。例如,允许从 1.12.x 升级到 1.13.x 或从 1.13.x 升级到 1.14.x,但不允许从 1.12.x 升级到 1.14.x。要从 1.12.x 升级到 1.14.x,首先从 1.12.x 升级到 1.13.x,然后从 1.13.x 升级到 1.14.x。
现在我们可以使用az aks upgrade
命令将 AKS 集群升级到 Kubernetes 版本 1.14.5。
az aks upgrade --resource-group jcbaksrg01 --name jcbaksclu01 --kubernetes-version 1.14.5
Listing 7-7az aks upgrade command
注意
根据您拥有的节点数量,升级 AKS 集群可能需要一些时间。升级操作所需的时间可以通过 10 分钟 x 集群中的节点总数来计算。在此示例中,升级操作必须在 30 分钟内成功,否则 AKS 将使操作失败,以避免不可恢复的群集状态。如果您遇到任何升级失败,请在达到该超时时间后重试群集升级操作。
您可以通过运行以下命令来确认集群升级是否成功。
az aks show --resource-group jcbaksrg01 --name jcbaksclu01 --output table
Listing 7-8Verify AKS upgrade operation
您应该会看到确认集群版本为 1.14.5 的输出
Name Location ResourceGroup KubernetesVersion ProvisioningState Fqdn
----------- ------------------ --------------- ------------------- ------------------- ---------------------------------------------------------
jcbaksclu01 australiasoutheast jcbaksrg01 1.14.5 Succeeded jcbaksclu01-dns-6bede950.hcp.australiasoutheast.azmk8s.io
Listing 7-9Verify AKS upgrade operation output
删除 AKS 集群
尽管您可以使用清单 7-10 中所示的一行代码来删除 AKS 集群,但是在继续此操作之前,请确保您已经备份了您的配置和数据。
az aks delete --name jcbaksclu01 --resource-group jcbaksrg01
Listing 7-10az aks delete command to delete an AKS cluster
创建虚拟节点
您可以使用虚拟节点来快速扩展 AKS 中的应用工作负载。使用虚拟节点的优势在于,您可以快速配置 pod,并且只需按每秒的执行时间付费。如果您正在使用集群自动缩放器(预览功能),则需要等到节点部署完成后再运行其他窗格。目前,只有 Linux 节点和 pod 支持虚拟节点。
截至目前,以下 Azure 区域支持虚拟节点:
-
澳大利亚东部(澳大利亚东部)
-
美国中部
-
美国东部(East US)
-
美国东部 2 (eastus2)
-
日本东部
-
北欧(北欧)
-
东南亚
-
美国中西部
-
西欧(西欧)
-
美国西部
-
美国西部 2 号
请记住,虚拟节点依赖于 Azure 容器实例(ACI)中可用的功能,因此它们还不支持以下场景:
-
使用服务主体提取 ACR 映像。你可以使用 Kubernetes 的秘密作为一个解决办法。
-
虚拟网络限制包括 VNet 对等、Kubernetes 网络策略和网络安全组的互联网出站流量。
-
初始化容器。
-
主机别名。
-
ACI 中 exec 的参数。
-
Daemonsets 不会将 pod 部署到虚拟节点。
-
虚拟节点不支持 Windows 服务器节点(目前在 AKS 的预览版中)。但是,您可以使用虚拟节点来调度 Windows 服务器容器,而不需要 AKS 群集中的 Windows 服务器节点。
注意
可以从以下 URL 找到创建和配置 AKS 集群以使用虚拟节点的完整分步说明:
使用 Azure CLI ( https://docs.microsoft.com/en-au/azure/aks/virtual-nodes-cli?view=azure-cli-latest
使用 Azure 门户( https://docs.microsoft.com/en-au/azure/aks/virtual-nodes-portal?view=azure-cli-latest
)
通过 Azure Kubernetes 服务使用虚拟 Kubelet
当使用 Azure Container Instances (ACI)时,你不必管理底层计算基础设施,因为 Azure 会为你做这些。在货物信息预报系统中运行的容器按每运行一个容器的秒数收费。您可以将虚拟 Kubelet provider for ACI 与 Linux 和 Windows 容器一起使用,并且可以在容器实例上调度它,就像它部署在常规 Kubernetes 节点中一样。
下图说明了虚拟 Kubelet 的工作原理。实质上,虚拟 Kubelet 将自己注册为 Kubernetes 集群中的一个节点。这使得开发人员可以通过将 Kubernetes 连接到其他 API,伪装成常规的 kubelet,从而允许自己的 API 与 pods 和容器进行交互。
注意
AKS 现在提供了对使用虚拟节点在 ACI 上调度容器的本地支持,目前只支持 Linux 容器。因此,建议只在需要调度 Windows 容器实例时才使用 Virtual Kubelet。
关于在 AKS 上使用 Virtual Kubelet 的分步说明,请参考以下网址: https://docs.microsoft.com/en-au/azure/aks/virtual-kubelet?view=azure-cli-latest
。
图 7-1
虚拟库伯莱架构
使用 Kubernetes 仪表板
Kubernetes 的默认仪表板体验包括一个 web 仪表板,您可以使用它来完成基本的管理任务。该仪表板允许您查看和监控应用的基本运行状况和指标,创建和部署容器服务,以及修改现有应用。仪表板在 kube-system 名称空间下运行。
以下命令为 jcbaskrg01 资源组中的 jcbaksclus01 集群启动 Kubernetes 仪表板。
注意
对于启用了 RBAC 的 AKS 集群,请确保在启动 Kubernetes 仪表板之前创建了 ClusterRoleBinding。默认情况下,Kubernetes 仪表板以最小的读者访问权限进行部署,并且可以显示 RBAC 访问错误。以下代码片段说明了如何使用kubectl create clusterrolebinding
命令为我们的示例创建绑定:
kubectl create clusterrolebinding kubernetes-dashboard --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard
。
az aks browse --resource-group jcbaksrg01 --name jcbaksclu01
Listing 7-11Starting the Kubernetes dashboard with az aks browse command
除非弹出窗口在浏览器中被阻止,否则在 Azure Cloud Shell 中执行上述命令后,您应该会被自动重定向到 web 浏览器中的新选项卡。如果没有,请将 Azure CLI 中显示的 URL 地址复制并粘贴到您的 web 浏览器中,如下所示。
图 7-3
Kubernetes 的控制板
图 7-2
蓝色 CLI 中的 open kuble dashboard
扩展蓝色立方体服务
当您在 Azure Kubernetes 服务中部署 n 个应用时,将需要根据需求增加或减少分配的计算资源。这将要求底层 Kubernetes 节点做出相应的改变。有些情况下,需要快速调配许多额外的应用实例。
本节探讨了 AKS 中的核心扩展概念,这些概念将帮助您实现上述目标。
手动缩放窗格或节点
为了测试您的应用如何响应 AKS 集群中资源可用性的变化,您可以手动扩展 pod(副本)和节点。通过手动扩展这些资源,您可以在 AKS 集群中定义一定数量的资源。为了手动缩放,首先要定义单元或节点数,然后 Kubernetes API 根据单元或节点数安排创建额外的单元或节点。
关于在 AKS 集群中扩展 pod 的完整教程可以从以下 URL 找到: https://docs.microsoft.com/en-au/azure/aks/tutorial-kubernetes-scale#manually-scale-pods
。在“手动扩展 AKS 集群节点”一节中,我们讨论了手动扩展 AKS 集群节点的步骤。
自动缩放窗格或节点
AKS 集群需要一种方法来自动扩展 pod 或节点,以便根据应用接收的流量来适应不断变化的应用需求。AKS 集群可以通过以下两种方式之一进行扩展:
-
horizontal podautoscaler(HPA):这利用 Kubernetes 集群中的度量服务器来监控 pod 的资源需求。如果应用请求更多资源,副本的数量会自动增加以满足需求。
-
集群自动缩放器:监视由于资源限制而无法在节点上调度的 pod。然后,群集可以自动增加节点数量。
水平吊舱自动缩放器
图 7-4
水平 pod 自动缩放架构
在 Kubernetes 中,水平 pod 自动缩放器(HPA)用于监控资源需求并自动缩放 pod 的数量。默认情况下,HPA 每 30 秒检查一次指标 API,以确定 pod 计数是否有任何必要的变化。如果在任何时候需要进行更改,pod 的数量会分别增加或减少。在 AKS 中,部署了 Metrics Server for Kubernetes 1.8+的 AKS 群集支持 HPA。
如果您正在为 AKS 集群配置水平单元自动缩放器,您将必须定义该集群可以运行的最小和最大单元数量。除此之外,您还可以声明一个要监控的指标,以及任何扩展决策所基于的指标,即 CPU 使用率。
关于在 AKS 集群中设置水平自动缩放器的完整教程可以从以下 URL 找到: https://docs.microsoft.com/en-au/azure/aks/tutorial-kubernetes-scale#autoscale-pods
。
注意
在每 30 秒发生一次的指标 API 检查之间,AKS 群集中以前的规模事件可能尚未成功完成。这种现象可能会导致 HPA 在之前的扩展事件能够掌握应用工作负载并相应地调整资源需求之前更改机架数量。为了最大限度地减少此类竞赛事件,在 AKS 集群中设置了冷却或延迟值。这些值描述了一个秤事件发生后,HPA 必须等待多长时间才能触发另一个秤事件。通过这样做,它将允许新的 pod 计数生效,并允许 Metrics API 反映新分配的工作负载。放大事件的默认延迟值为 3 分钟,而缩小事件的默认延迟值为 5 分钟。目前,用户不能设置这些冷却值。
群集自动缩放器(预览)
图 7-5
集群自动缩放架构
Cluster autoscaler(预览版)可以根据节点池中请求的计算资源调整节点数量,以快速响应不断变化的 pod 需求。如果集群自动缩放器决定需要资源变化,它可以相应地增加或减少 AKS 集群中的节点数量。运行 Kubernetes 1.10.x 或更高版本的支持 RBAC 的 AKS 集群支持集群自动缩放功能。
通常,群集自动缩放器与水平 pod 自动缩放器一起使用。HPA 根据应用需求增加或减少单元的数量,而集群自动缩放器会调整运行这些额外单元所需的节点数量。
注意
集群自动缩放是 AKS 中的一个预览功能。
关于集群自动缩放器入门的完整教程可以从以下 URL 找到: https://docs.microsoft.com/en-au/azure/aks/cluster-autoscaler
。
使用 Azure 容器实例按需爆发
图 7-6
Azure 容器实例爆炸
与 Azure Container Instances (ACI)集成允许您快速扩展 AKS 集群。Kubernetes 中的内置组件可以扩展 pod 和节点数量。但是,如果您的应用要求快速扩展,HPA 可能会调度比使用节点池中的现有计算资源所能提供的更多的 pod。这种现象会触发群集自动缩放器在节点池中部署额外的节点;但是,这些额外的节点可能需要一些时间来配置,并允许 Kubernetes 调度程序在这些节点上运行 pods。
连接到 AKS 的 ACI 成为您的 AKS 集群的安全和逻辑扩展。目前有两种方法可以在 AKS 上启用 ACI:
-
虚拟 Kubelet :当安装在 AKS 集群中时,该组件可以将 ACI 呈现为虚拟 Kubernetes 节点。它支持 Linux 和 Windows 节点。
-
虚拟节点:目前在预览版中,这些节点被部署到与您的 AKS 集群相同的 VNet 中的一个附加子网。该虚拟网络允许 ACI 和 AKS 之间的流量得到保护。目前仅支持 Linux 节点。
Azure Kubernetes 服务的存储选项
部署到 AKS 集群的应用需要存储来存储和检索它们的数据。对于一些工作负载,这些存储可以是节点上的本地快速存储,可以在删除 pod 时释放,而其他一些工作负载可能需要 Azure 中托管的持久数据存储。如果在不同的节点上重新安排单元,则多个单元可能需要共享相同的数据卷和/或重新连接数据卷。还可能需要将敏感数据或应用配置呈现到 pod 中。图 7-7 描述了 AKS 集群的存储架构。
图 7-7
AKS 中的存储架构
在本节中,我们将探讨 AKS 中的核心概念,这些概念解释了如何为您的应用工作负载提供存储。
卷
一个卷代表一种在整个应用生命周期中跨 pod 存储、检索和持久化数据的方法。通常,在 AKS 上存储和检索数据所需的容量是基于 Azure 存储的。这些数据卷既可以手动创建,然后直接分配给 pod,也可以在需要时由 AKS 自动创建和分配。这些数据卷可以使用
-
Azure Disks :这些可以用来创建一个 Kubernetes DataDisk 资源。Azure 磁盘可以使用 Azure 高级存储或 Azure 标准存储。对于生产和开发工作负载,建议使用高级存储。它们以读写一次的方式装载,因此只对单个节点可用。
-
Azure 文件用于将由 Azure 存储帐户支持的 SMB 3.0 共享安装到 pods。使用 Azure 文件,您可以在多个节点和单元之间共享数据。Azure 文件支持 Azure 高级存储和 Azure 标准存储。
还可以利用 Kubernetes 卷将数据注入到容器使用的 pod 中。Kubernetes 中的其他卷类型包括
-
emptyDir :用作 pod 的临时空间
-
secret :用于将敏感数据注入 pod,如密码
-
configMap :用于将键值对属性注入到 pod 中,比如应用配置信息
持久卷
持久卷(PV)由 Kubernetes API 创建和管理。它可以在单个 pod 的生命周期之后继续存在,而作为 pod 生命周期的一部分创建的传统卷只会在 pod 被删除之前一直存在。您可以使用 Azure 磁盘或文件来提供 PV。
持久卷可以由集群管理员手动创建,也可以由 Kubernetes API 服务器动态生成。如果调度请求当前不可用的存储,Kubernetes 将创建底层 Azure 磁盘或文件存储,并将其附加到 pod。这个场景被称为动态预配置,它使用一个存储类来确定需要什么类型的 Azure 存储。
存储类别
为了对不同的存储层进行分类,您可以创建一个存储类。StorageClass 还定义了回收策略。当 pod 被删除,并且可能不再需要持久卷时,回收策略控制 Azure 存储资源的行为。删除一个单元后,存储资源既可以删除,也可以保留以供将来的单元使用。
AKS 中可以创建两个初始存储类:
-
默认:利用 Azure 标准存储创建托管磁盘。回收策略声明,当相应的 pod 被删除时,Azure 磁盘也将被删除。
-
managed-premium :利用 Azure Premium 存储创建托管磁盘。回收策略声明,当相应的 pod 被删除时,Azure 磁盘也将被删除。
如果在创建 PV 时未指定 StorageClass,则使用默认的 StorageClass。
在以下 YAML 清单中,声明将使用高级管理磁盘,并且在删除 pod 时必须保留 Azure 磁盘:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: managed-premium-retain
provisioner: kubernetes.io/azure-disk
reclaimPolicy: Retain
parameters:
storageaccounttype: Premium_LRS
kind: Managed
Listing 7-12Defining a storage class in YAML
持续量声明
如果您想要创建具有定义的存储类别、访问模式和大小的磁盘或文件存储,请定义一个 PersistentVolumeClaim。如果没有现有的资源来为基于其 StorageClass 的声明提供服务,那么 Kubernetes API 服务器可以动态地提供底层存储资源。一旦将卷连接到 pod,pod 定义也将包括卷装载。
在将可用存储资源分配给请求该资源的 pod 后,PV 将绑定到 PersistentVolumeClaim。永久卷与声明的映射是 1:1
下面是一个 YAML 清单示例,它表示托管高级存储类的 PV 索赔,磁盘大小为 5 Gi。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: azure-managed-disk
spec:
accessModes:
- ReadWriteOnce
storageClassName: managed-premium
resources:
requests:
storage: 5Gi
Listing 7-13Defining a PersistentVolumeClaim in YAML
创建 pod 定义时,会指定一个 PV 声明来请求所需的存储。在这里,您还可以为您的应用指定 volumeMount 来读取和写入数据。下面的 YAML 清单说明了如何使用前面的 PV 声明在/mnt/azure 安装卷。
kind: Pod
apiVersion: v1
metadata:
name: nginx
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/mnt/azure"
name: volume
volumes:
- name: volume
persistentVolumeClaim:
claimName: azure-managed-disk
Listing 7-14Defining a volumeMount in a PersistentVolumeClaim in YAML
我们简要讨论了适用于 AKS 工作负载的存储选项。下一步是为 AK 创建动态和静态卷。Microsoft 文档中的以下文章全面概述了如何做到这一点:
-
使用 Azure 磁盘创建静态卷(
https://docs.microsoft.com/en-au/azure/aks/azure-disk-volume
)。 -
使用 Azure 文件(
https://docs.microsoft.com/en-au/azure/aks/azure-files-volume
)创建静态卷。 -
使用 Azure 磁盘创建动态卷(
https://docs.microsoft.com/en-au/azure/aks/azure-disks-dynamic-pv
)。 -
使用 Azure 文件(
https://docs.microsoft.com/en-au/azure/aks/azure-files-dynamic-pv
)创建动态卷。
Azure Kubernetes 服务中的网络
微服务方法中的应用组件必须协同工作来处理它们期望的任务。这种应用通信可以使用 Kubernetes 提供的一些组件来实现。例如,应用可以在内部或外部公开,可以进行负载均衡以实现高可用性,并具有 SSL。入口流量和多个组件路由的 TLS 终端。此外,出于安全考虑,开发人员可能需要您限制 pod 和节点之间的网络流量。
在本节中,我们将深入了解 AKS 的核心网络概念,以及为您的 pod 和节点提供安全网络连接的一些示例。
Kubenet vs. Azure 容器网络接口(CNI)
AKS 群集使用以下两种网络模型之一:
Kubenet(基本)网络
这是 AKS 集群的默认配置选项。在 kubenet 中,AKS 节点从 Azure VNet 子网获得一个 IP 地址。Pods 从逻辑上不同于节点的 Azure VNet 子网的地址空间接收 IP 地址。为了让 pods 访问 Azure VNet 上的资源,需要配置网络地址转换(NAT)。流量的源 IP 地址通过 NAT 转换为节点的主 IP 地址。
节点使用 kubenet Kubernetes 插件。您可以允许 Azure Fabric 为您创建和配置 VNet,或者将您的 AKS 集群部署到预定义 VNet 的现有子网中。即使您部署到预定义的 VNet,也只有节点会收到可路由的 IP 地址;pods 使用 NAT 与 AKS 集群外部的其他资源进行通信。
Azure 容器网络接口(CNI) -高级网络
每个 pod 从子网获得一个 IP 地址,如果您使用 Azure CNI 模型,可以直接访问它。但是请记住,这些 IP 地址在整个 VNet 网络空间中必须是唯一的,并且必须提前做好规划。每个节点支持的最大 pod 数量有一个配置参数。然后为该节点保留每个节点相同数量的 IP 地址。
下表列出了 kubenet 和 Azure CNI 之间的行为差异。
表 7-1
库伯内特和蔚蓝 CNI 之间的行为差异
|能力
|
库伯内特
|
CNI 蓝色
|
| --- | --- | --- |
| 在现有或新的虚拟网络中部署集群 | 受支持–手动应用 udr | 支持 |
| Pod-pod 连接 | 支持 | 支持 |
| Pod-VM 连接性;同一虚拟网络中的虚拟机 | 由 pod 启动时工作 | 双向工作 |
| Pod-VM 连接性;对等虚拟网络中的虚拟机 | 由 pod 启动时工作 | 双向工作 |
| 使用 VPN 或快速路由进行内部访问 | 由 pod 启动时工作 | 双向工作 |
| 对由服务端点保护的资源的访问 | 支持 | 支持 |
| 使用负载均衡器服务、应用网关或入口控制器公开 Kubernetes 服务 | 支持 | 支持 |
| 默认 Azure DNS 和专用区域 | 支持 | 支持 |
表 7-2 从高层次上列出了 kubenet 和 Azure CNI 的优缺点。
表 7-2
库伯内特 vs 蔚蓝 CNI 的优缺点
|模型
|
优势
|
不足之处
|
| --- | --- | --- |
| 库伯内特 | 节省 IP 地址空间。使用 Kubernetes 内部或外部负载均衡器从集群外部访问 pod。 | 您必须手动管理和维护用户定义的路线(udr)。每个集群最多 400 个节点。 |
| CNI 蓝色 | pod 获得完全的虚拟网络连接,并且可以从群集外部直接访问。 | 需要更多的 IP 地址空间。 |
无论您选择了哪种网络模型,AKS 的支持策略都描述了网络调整功能,例如您可以在 AKS 集群中使用的服务端点和 udr:
-
如果您为 AKS 群集手动创建虚拟网络资源,则在配置您自己的 udr 或服务端点时会得到支持。
-
如果 Azure 平台自动为您的 AKS 集群创建虚拟网络资源,则不支持手动更改这些 AKS 管理的资源来配置您自己的 udr 或服务端点。
注意
有关 AKS 支持策略的完整记录,请访问以下网址: https://docs.microsoft.com/en-au/azure/aks/support-policies
。
网络安全组和网络策略
不建议手动配置网络安全组规则来过滤 AKS 群集中的 pod 流量。Azure 平台将创建和更新适当的规则,作为 AKS 托管服务的一部分。为了自动将流量过滤规则应用到 pod,您可以利用网络策略。一方面,它是 AKS 中可用的功能,允许您控制 pod 之间的流量。您可以根据分配的标签、命名空间或流量端口等设置来决定是允许还是拒绝流量。另一方面,网络安全组是针对 AKS 节点的,而不是 pod。
注意
有关在 AKS 中使用 Azure 网络策略保护 pod 流量的分步说明,请访问以下 URL: https://docs.microsoft.com/en-au/azure/aks/use-network-policies
。
Azure Kubernetes 服务中的访问和身份
在 Azure 中,有多种方法来验证和保护 AKS 集群。基于角色的访问控制(RBACs)允许授予用户或组仅访问他们需要的资源的权限。通过将 AKS 与 Azure Active Directory 集成,您能够进一步增强安全性和权限结构。本节高度概括了操作 AKS 集群时可用的访问和身份选项。
不可思议的服务帐户
服务帐户是 Kubernetes 中的主要用户类型,它存在于 Kubernetes API 中,并由它管理。服务帐户凭证存储为 Kubernetes 机密,这允许授权的 pods 使用它们与 API 服务器通信。API 请求为服务帐户或常规用户帐户提供身份验证令牌。普通用户帐户被用来为使用 AKS 集群的管理员或开发人员提供传统的访问,尽管 Kubernetes API 本身并没有为这种场景提供身份管理解决方案。通过将 AKS 与 Azure Active Directory 集成,可以实现这个目标。
Azure 活动目录集成
Azure Active Directory (AAD)是一个多租户、基于云的目录和身份管理解决方案,提供核心目录服务、应用访问管理和身份保护。您可以将本地身份集成到 AKS 集群中,通过将 AKS 与 AAD 集成来提供统一的帐户管理和安全流程。
例如,在集成了 AAD 的 AKS 集群中,您可以授权用户或组访问某个名称空间内或整个集群中的 Kubernetes 资源。为了检索kubectl
配置上下文,用户可以执行az aks get-credentials
命令。之后,当用户使用kubectl
与 AKS 集群交互时,他们将被提示使用各自的 Azure AD 凭据登录。这样,用户只能访问 AKS 集群管理员定义的资源。
Azure 基于角色的访问控制(RBACs)
除了 Kubernetes API 提供的 RBAC,AKS 集群访问还可以通过 Azure 基于角色的访问控制(RBAC)来管理。区别在于,Kubernetes RBAC 旨在处理您的 AKS 集群内的资源,而 Azure RBAC 旨在处理您的 Azure 订阅内的资源。Azure RBAC 使您能够创建角色定义,概述应用于 AKS 群集的权限。然后,您可以为包含已定义范围的角色定义分配用户或组,该范围可以是单个资源、资源组或整个 Azure 订阅。
角色、集群角色、角色绑定和集群角色绑定
在 Kubernetes RBAC,您首先将权限定义为一个角色。Kubernetes 角色授予权限,没有拒绝权限的概念。角色用于在名称空间内授予权限。
ClusterRole 的用途类似于角色,但是 ClusterRole 可以应用于整个集群的资源,而不是特定的名称空间。
当您定义了角色后,您可以通过角色绑定为这些 Kubernetes RBAC 分配权限。在 AAD 集成的 AKS 集群中,绑定是 Azure AD 用户被授予在集群中执行操作的权限的方式。角色绑定用于为已定义的名称空间分配角色,在该名称空间中,您可以隔离对各个集群的访问。
另一方面, ClusterRoleBinding 的工作方式与角色绑定相同,但是可以应用于整个集群中的资源,而不是特定的名称空间。在需要授权管理员或支持工程师访问 AKS 集群中所有资源的情况下,这种方法非常理想。
使用 Azure 策略控制部署(预览)
Azure Policy 可以与 AKS 集成,因此您可以以集中和一致的方式将策略强制应用到您的 AKS 集群。通过使用看门人,Azure Policy 允许您集中管理和报告 Azure 资源和 AKS 集群的合规状态,这是一个针对开放策略代理(OPA)的准入控制器 webhook。
按照以下步骤启用该功能并将其应用到您的 AKS 集群。
启用预览
首先,您必须启用Microsoft.ContainerService
资源提供者和Microsoft.PolicyInsights
资源提供者,然后被批准加入预览。以下示例说明了如何在 Azure Cloud Shell 中使用 Azure CLI 实现这一点。
# Provider register: Register the Azure Kubernetes Services provider
az provider register --namespace Microsoft.ContainerService
# Provider register: Register the Azure Policy provider
az provider register --namespace Microsoft.PolicyInsights
# Feature register: enables installing the add-on
az feature register --namespace Microsoft.ContainerService --name AKS-AzurePolicyAutoApprove
# Feature register: enables the add-on to call the Azure Policy resource provider
az feature register --namespace Microsoft.PolicyInsights --name AKS-DataplaneAutoApprove
Listing 7-15Join the AKS Policy preview via Azure CLI
Azure 策略加载项
这个附加组件安装在 azure-policy 名称空间中,将 azure 策略服务连接到网守准入控制器。以下是该附加组件的功能:
-
使用 Azure 策略检查对 AKS 群集的分配
-
下载并缓存策略详细信息,包括作为配置映射的 rego 策略定义
-
对 AKS 群集运行完全扫描符合性检查
-
向 Azure Policy 报告审核和合规详细信息
安装先决条件
在 AKS 集群中安装插件之前,您需要安装预览扩展。为此,请遵循以下步骤:
-
确保您运行的是 Azure CLI 版本 2.0.62。运行 az - version 来查找版本。
-
AKS 集群必须是 1.10 版或更高版本。以下 Azure CLI 摘录说明了如何检查这一点。
-
为
AKS, aks-preview
安装 0.4.0 版 Azure CLI 预览版扩展。
az aks list
Listing 7-16Check AKS version
# Install/update the preview extension
az extension add --name aks-preview
# Validate the version of the preview extension
az extension show --name aks-preview --query [version]
Listing 7-17Install Azure CLI preview extension for AKS
注意
如果已经部署了 aks-preview 扩展,请卸载执行az extension update --name aks-preview
命令的任何更新。
正在安装 Azure 策略加载项
一旦安装了前面的先决条件,您就可以继续安装 Azure Policy 插件。以下 Azure CLI 摘录说明了如何做到这一点。
az aks enable-addons --addons azure-policy --name jcbaksclu01 --resource-group jcbaksrg01
Listing 7-18Install Azure Policy add-on
将策略定义分配给 AK
目前 Azure 的 AKS 策略是有限的预览版,只支持内置的策略定义。您可以找到使用 Azure 门户管理 AK 的内置策略,如下所示:
-
点击左侧窗格中的所有服务,然后搜索并选择策略。
-
在 Azure Policy 页面,选择定义。
-
从类别下拉列表中,点击全选,然后选择 Kubernetes 服务。
-
选择要应用的策略定义,然后选择分配按钮。
注意
在为 AKS 定义分配 Azure 策略时,确保范围必须包括 AKS 群集资源。
策略验证
Azure Policy 插件每 5 分钟向 Azure Policy Service 检查一次策略分配的变化。azure-policy 命名空间中的所有 configmaps 都被删除,然后在此刷新周期中由附加组件为网守重新创建。
该插件要求每 5 分钟对群集进行一次全面扫描。一旦从全面扫描中收集到详细信息,以及网关守护设备对尝试更改群集的任何实时评估,结果将报告回 Azure Policy,以包括合规性详细信息,如 Azure 策略分配。在审计周期中,仅返回活动策略分配的结果。
注意
不建议或不支持对命名空间进行更改,尽管群集管理员可能拥有对 azure-policy 命名空间的权限,并且任何手动更改都会在刷新周期中丢失。
Azure 策略加载项日志
Azure Policy 附加组件日志作为 Kubernetes 控制器/容器保存在 AKS 集群中。这些日志显示在 AKS 集群的 Insights 页面中。
网关守护设备日志
您需要检查新资源请求的日志。按照以下 URL 中的过程在 AKS 中启用和查看 Kubernetes 主节点日志: https://docs.microsoft.com/en-au/azure/aks/view-master-logs
。
清单 7-19 是查看新资源请求的拒绝事件的示例查询。
| where Category == "kube-audit"
| where log_s contains "admission webhook"
| limit 100
Listing 7-19KQL query to view denied events on new resource requests
要查看网关守护设备容器中的日志,请遵循上一篇文章中的步骤,并检查诊断设置窗格中的 kube-apiserver 选项。
Azure Kubernetes 服务中的安全概念
AKS 群集的安全性与数据中心的任何其他资源一样至关重要。网络策略和秘密等 Kubernetes 安全组件得到了 Azure 功能的补充,如网络安全组和协调的 AKS 集群升级。
主安全
Kubernetes 主组件是 Azure 提供的 AKS 托管服务的一部分。每个 AKS 集群都有自己的单租户、专用的 Kubernetes master 来提供 Azure 中的 API 服务器、调度程序等。这个主机由 Azure 管理和维护。Kubernetes API 服务器使用公共 IP 地址和完全限定的域名(FQDN)的默认行为。对 API 服务器的访问可以通过使用 Kubernetes RBACs 和 Azure Active Directory 来控制。
节点安全性
AKS 节点是由你自己管理和维护的 Azure 虚拟机。Linux AKS 节点运行在带有莫比容器运行时的优化 Ubuntu 发行版上。Windows 服务器节点(目前在 AKS 中预览版)运行优化的 Windows Server 2019 版本和莫比容器运行时。在 AKS 集群中创建或扩展操作期间,这些节点会自动部署最新的操作系统安全更新和配置。
以下是规划 AKS 节点安全性时的一些事实和注意事项:
-
Azure 平台每晚都会自动将 OS 安全补丁应用到 Linux 节点上。
-
如果 Linux 操作系统安全更新需要重新启动主机,它不会自动执行。
-
您既可以手动重启 Linux 节点,也可以使用 Kubernetes 的开源重启守护程序 Kured 。
-
Windows Update 不会自动运行并应用 Windows 服务器节点的最新更新。
-
您应该自己对 AKS 群集中的 Windows 服务器节点池执行升级。此升级过程会创建运行最新 Windows Server 映像和修补程序的节点,然后删除旧节点。
-
默认情况下,节点部署在专用虚拟网络子网中,没有分配公共 IP 地址。SSH 默认启用,仅在使用内部 IP 地址进行故障排除和访问时可用。
-
节点使用 Azure 管理的磁盘进行存储。对于大多数虚拟机 SKU,这些都是优质磁盘,存储的数据在 Azure 平台内自动加密。
-
需要额外的安全功能,如 Pod 安全策略或更细粒度的基于角色的访问控制(RBAC ),以保护节点免受多租户使用中可能出现的漏洞攻击。
-
对于敌对的多租户工作负载,您应该通过利用虚拟机管理程序级别的安全性来使用物理隔离的集群,其中 Kubernetes 的安全域成为整个集群,而不是单个节点。
-
多租户工作负载的最佳实践是使用逻辑隔离来分隔团队和项目。建议尽量减少为隔离团队或应用而部署的物理 AKS 集群的数量。
集群升级
AKS 集群升级过程包括从集群中单独隔离节点,以便不能在这些节点上安排新的 pod。然后,这些节点被清空,并按照以下过程进行升级:
-
一个新节点部署到运行最新操作系统映像和修补程序的节点池中。
-
现有节点中的一个被识别并标记用于升级。此节点上的 pod 会在节点池中的其他节点上正常终止和调度。
-
然后从 AKS 群集中删除该目标节点。
-
群集中的下一个节点使用相同的过程进行隔离和排空,直到作为升级过程的一部分,所有节点都被成功替换。
不可告人的秘密
敏感数据如访问凭证或密钥可以通过使用一个Kubernetes?? 秘密被摄取到 pod 中。这个秘密首先是使用 Kubernetes API 创建的,当您定义您的 pod 或部署时,可以请求一个特定的秘密。这些秘密仅提供给具有需要秘密的调度 pod 的节点,并且存储在 tmpfs 中,而不是写入磁盘中。当节点上的最后一个 pod 请求删除密码时,密码将从节点的 tmpfs 中删除。此外,Kubernetes 的秘密存储在一个定义的名称空间中,只能由同一名称空间中的 pod 访问。
通过使用 Kubernetes secrets,您可以最大限度地减少 pod 或服务 YAML 清单中定义的敏感信息。在这里,您将请求存储在 Kubernetes API 服务器中的秘密,作为您的 YAML 清单的一部分。通过使用这种方法,您只提供了对秘密的特定 pod 访问。
注意
原始机密清单文件包含 base64 格式的机密数据,因此,该文件应被视为敏感信息,不应提交给源代码管理。
监视蓝色立方体服务
操作 Azure Kubernetes 服务的一个重要部分是能够监控在 AKS 实例中运行的集群、节点和工作负载。运行生产工作负载需要可靠的可靠性。Azure 附带了 Kubernetes,Azure Monitor 中提供了开箱即用的容器监控。在这一节中,我们将深入探讨 Azure Monitor 中可用的 Kubernetes 和容器监控服务。
Azure 容器监视器
概观
Azure Monitor 中的监控服务被称为 Azure Monitor for containers。Azure Monitor for containers 从两个角度为您提供监控:第一个角度直接来自 AKS 集群,第二个角度是您的订阅中的所有 AKS 集群。监控查看两个关键区域“健康状态”和“性能图表”,包括
-
洞察力:监控 Kubernetes 集群和容器。
-
指标:基于指标的聚类和 pod 图表。它基于一个时间序列数据库,该数据库直接从 AKS 资源提供程序收集数据,以获得 pod 和节点上的基本和标准性能指标。
-
Log Analytics: K8s and container logs viewing and search. It is the platform where Azure Monitor for containers store the data. You can run KQL queries to view all telemetries that Azure Monitor for containers collects such as perf, health, kubernetes events, container logs, and inventory.
图 7-8
Azure 容器架构监视器
启用监控
启用 AKS 监控的最简单方法是部署 AKS 集群。有关部署 AKS 集群的详细信息,请参考第五章“部署 Azure Kubernetes 服务”。
可以使用以下方法之一启用对现有 AKS 集群的监控:
-
在 Azure Monitor 中或 Azure 门户的 AKS 集群中
-
azure PowerShell cmdlet New-AzResourceGroupDeployment 使用 ARM 模板此处:
https://docs.microsoft.com/en-us/azure/azure-monitor/insights/container-insights-enable-existing-clusters#enable-using-an-azure-resource-manager-template
-
蓝色 CLI
-
仿地成形
启用 AKS 集群监控的最佳和最快方式是从 Azure Cloud Shell 中的 Azure CLI。要从 web 浏览器执行此操作,请导航至 https://shell.azure.com
PowerShell 并运行以下程序。
az aks enable-addons -a monitoring -n ExistingAKSCluster -g ExistingAKSClusterResourceGroup
Listing 7-20Enabling Azure Monitor for containers using Azure CLI
Azure 监视器
在 Azure Monitor 中,你会在洞察下找到容器。在这里,您将看到 Azure 订阅中所有 AKS 群集的运行状况摘要。此外,您将看到 AKS 集群有多少个节点和系统/用户单元,以及节点或单元是否有任何健康问题。从这里单击一个集群,它会将您带到 AKS 集群本身的 Insights 部分。单击 AKS 集群会将您带到 Azure Monitor for containers 的 Insights 部分,该部分位于实际的 AKS 集群上。在这里,您将看到见解、指标和日志。现在让我们深入了解这三个领域。
图 7-9
Azure Monitor for containers 概述页面
洞察力
在 Insights 区域,您会发现许多关于监控 AKS 集群的有用数据。在 Insights 中,有四个区域:集群、节点、控制器和容器。
串
在“Cluster”选项卡中,您会发现包含 AKS 集群运行状况关键性能指标的图表。它提供了节点计数和状态以及单元计数的性能图表,以及群集内的聚合节点内存和 CPU 利用率。在这里,您可以将时间范围从实时、小时更改为天,并添加筛选器以将范围缩小到特定信息,如服务、命名空间、节点池和您想要查看的节点。
节点
在 Nodes 选项卡上,您将看到 AKS 集群中运行的节点,以及正常运行时间、节点上的 pod 数量、CPU 使用率、内存工作集和内存 RSS。您可以单击节点旁边的箭头将其展开,显示正在其上运行的窗格。这为您提供了一种快速查看 AKS 集群中嘈杂邻居的方法。
控制器
在控制器选项卡上,您可以找到集群控制器的运行状况。同样,这里您将看到每个控制器的 CPU 使用率、内存工作集和内存 RSS,以及运行控制器的是什么。例如,您可以看到 kubernetes-dashboard pod 在 kubernetes-dashboard 控制器上运行。
您还可以查看 kubernetes-dashboard 窗格的属性。这些属性将为您提供诸如 pod 名称、pod 状态、Uid、标签等信息。
容器
在 Containers 选项卡上,您将找到 AKS 集群中的所有容器。和其他选项卡一样,您可以看到 CPU 使用率、内存工作集和内存 RSS。您还将看到状态、它所属的单元、它正在运行的节点、它的正常运行时间以及它是否有任何重新启动。
您还可以在“容器”选项卡中查看容器日志。为此,请选择一个容器来显示其属性。在属性中,您可以单击查看容器实时日志(如下图所示)或查看容器日志。每三分钟收集一次容器日志数据。STDOUT 和 STDERR 是从每个 Docker 容器发送到日志分析的日志输出。
图 7-10
Azure Monitor for containers 实时日志和事件
点击查看实时数据(预览)将带您进入日志分析日志搜索页面,该容器的日志和事件显示在结果窗格中。
注意
动态数据在节点、控制器和容器选项卡中可用。它们将向您显示 kubernetes 事件(每个集群、名称空间和/或节点和/或 pod)和容器日志。
图 7-11
Azure Monitor for containers 分析视图
kube-system 当前未被收集并发送至日志分析。如果您不熟悉 Docker 日志,可以在这里的这篇 Docker 日志文章中找到关于 STDOUT 和 STDERR 的更多信息: https://docs.docker.com/config/containers/logging
。
注意
如果您想要为 kube-system 收集日志,您可以按照以下条款更改配置图: https://docs.microsoft.com/en-us/azure/azure-monitor/insights/container-insights-agent-config
韵律学
在 metrics 区域,您可以看到基于指标的节点和 pod 图表,这些图表有助于您了解有关 AKS 集群的重要信息。下面的屏幕截图显示了几个示例图表,这些图表根据命名空间和集群中的可用核心总数按阶段划分显示了 pod。
图 7-12
Azure 容器监视器度量视图
在撰写本书时,唯一可用的标准度量名称空间是Microsoft . container service/managed clusters(来自 AKS 资源提供商)和自定义度量名称空间 insights.container/nodes 和 insights.container/pods (来自 container insights)。聚合可以是总和或平均值,您可以在下面的屏幕截图中看到这些指标:
图 7-13
Azure 容器监视器可用指标
在 metrics 区域中,您可以将图表固定到 Azure dashboard,并且可以基于条件(如窗格何时处于失败状态)创建警报。
图 7-14
为 Azure Monitor for containers 创建警报规则
日志分析
日志分析是 Azure Monitor 的一个特性。日志分析被许多 Azure 服务用来查看日志和搜索;分析数据以确定趋势、模式和问题;通过机器学习进行异常检测;以及更多。在日志分析中,您可以深入了解您的 AKS 集群和容器。以下屏幕截图显示了在 Azure Monitor for containers 中收集的日志架构:
图 7-15
Azure Monitor for containers 日志架构
ContainerInsights 架构中的数据类型显示在日志分析搜索结果中。显示日志分析搜索页面的一种方法是在 AKS 群集中单击日志。从搜索页面,您可以筛选搜索结果或运行查询。
从“日志分析搜索”页面,您可以构建查询来检索限定范围的数据。下面是三个用于检索 AKS 数据的日志分析查询示例。
Pods that have a restart count greater than 0 in the last 48 hours
let startTimestamp = ago(48hrs);
KubePodInventory
| where ClusterName =~ "AKSCLUSTERNAME"
| where ContainerRestartCount > 0
| where isnotnull(Name)
Listing 7-21KQL query samples for retrieving AKS data
容器生命周期
ContainerInventory
| project Computer, Name, Image, ImageTag, ContainerState, CreatedTime, StartedTime, FinishedTime
| render table
久别事件
KubeEvents_CL
| where not(isempty(Namespace_s))
| sort by TimeGenerated desc
| render table
通过日志分析创建警报规则
我们使用下面的示例查询来返回基于所有阶段的 pod 阶段计数—失败的 、 待定的 、 未知的 、 正在运行的 或 成功的—通过日志分析查询来创建警报规则。
let endDateTime = now();
let startDateTime = ago(1h);
let trendBinSize = 1m;
let clusterName = '<your-cluster-name>';
KubePodInventory
| where TimeGenerated < endDateTime
| where TimeGenerated >= startDateTime
| where ClusterName == clusterName
| distinct ClusterName, TimeGenerated
| summarize ClusterSnapshotCount = count() by bin(TimeGenerated, trendBinSize), ClusterName
| join hint.strategy=broadcast (
KubePodInventory
| where TimeGenerated < endDateTime
| where TimeGenerated >= startDateTime
| distinct ClusterName, Computer, PodUid, TimeGenerated, PodStatus
| summarize TotalCount = count(),
PendingCount = sumif(1, PodStatus =~ 'Pending'),
RunningCount = sumif(1, PodStatus =~ 'Running'),
SucceededCount = sumif(1, PodStatus =~ 'Succeeded'),
FailedCount = sumif(1, PodStatus =~ 'Failed')
by ClusterName, bin(TimeGenerated, trendBinSize)
) on ClusterName, TimeGenerated
| extend UnknownCount = TotalCount - PendingCount - RunningCount - SucceededCount - FailedCount
| project TimeGenerated,
TotalCount = todouble(TotalCount) / ClusterSnapshotCount,
PendingCount = todouble(PendingCount) / ClusterSnapshotCount,
RunningCount = todouble(RunningCount) / ClusterSnapshotCount,
SucceededCount = todouble(SucceededCount) / ClusterSnapshotCount,
FailedCount = todouble(FailedCount) / ClusterSnapshotCount,
UnknownCount = todouble(UnknownCount) / ClusterSnapshotCount
| summarize AggregatedValue = avg(PendingCount) by bin(TimeGenerated, trendBinSize)
Listing 7-22KQL query sample to retrieve pod phase counts based on all phases
注意
以下为容器资源利用率创建预警规则的过程需要利用新的日志预警 API,如下 URL 所示: https://docs.microsoft.com/en-us/azure/azure-monitor/platform/alerts-log-api-switch
。
按照以下步骤,使用日志分析查询在 Azure Monitor 中创建日志警报:
-
登录 Azure 门户,从左侧窗格中选择 Monitor ,导航到 Insights ,然后选择 Containers 。
-
从受监控集群选项卡的列表中选择一个集群。
-
选择日志打开监控下的 Azure Monitor 日志页面。在该页面中,您可以编写和执行 Azure Log Analytics 查询。
-
在日志页面,选择+新建预警规则。
-
在条件部分,当<逻辑未定义> 自定义日志条件时,选择。因为我们直接从 Azure Monitor 日志页面创建警报规则,所以会自动选择自定义日志搜索信号类型。
-
将列表 7-22 中的查询粘贴到搜索查询字段中。
-
按照以下步骤配置警报:
-
在基于的下拉列表中选择公制测量。这里,一个度量测量为查询中值高于我们指定阈值的每个对象创建一个警报。
-
在条件下,选择大于的,输入 75 作为 CPU 和内存利用率告警的初始基线阈值。对于低磁盘空间警报,输入 90 。您可以输入符合标准的不同值。
-
在基于部分的触发预警下,选择连续违规。在下拉列表中选择大于的,输入 2 。
-
如果您想为容器 CPU 或内存利用率配置一个警报,选择上聚合下的容器名。如果要为集群节点配置低磁盘警报,选择 ClusterId 。
-
在基于段评估的下,将周期值配置为 60 分钟。这样,规则将每隔 5 分钟执行一次,并将返回从当前时间开始的最后一个小时内创建的记录。当您将时间跨度设置为较宽的窗口(这将导致潜在的数据延迟)时,可确保查询返回数据,以避免任何从未触发警报的误报。
-
-
点击完成。
-
在警报规则名称字段中提供一个有意义的名称。您还可以指定一个描述,它提供了这个警报的详细信息。最后,为此警报选择适当的严重性级别。
-
在创建时接受启用规则的默认值,以便立即激活警报。
-
您可以选择现有的操作组或创建新组。这是确保每次触发此警报时采取相同操作的方法。您可以根据您的 ITSM 团队管理事件的方式来配置此部分。
-
点击创建预警规则完成预警规则。规则立即开始执行。
有关使用日志分析查询语言创建警报的更多信息,您可以在此处访问微软文档: https://docs.microsoft.com/en-us/azure/azure-monitor/insights/container-insights-alerts
。
库伯勒原木
如果某个节点有问题,应该使用 Azure Monitor for containers 中提供的节点监控开始故障排除。如果需要超越 Azure Monitor for containers,可以使用 kubelet 日志。您可以使用 journalctl 从任何 AKS 节点查看 kubelet 日志。为此,您需要首先 SSH 到您想要查看日志的集群节点。通过 SSH 连接到节点后,执行以下语法。
sudo journalctl -u kubelet -o cat
Listing 7-23kubelet log retrieval
这将开始滚动 kubelet 日志,让您深入了解节点上发生的活动。
Kubernetes 主组件日志
值得注意的是,使用 AKS 时,默认情况下不会收集 Kubernetes 主节点日志。没有收集这些日志,因为 AKS 是微软的托管服务,它们管理主 Kubernetes 节点。因此,深入研究主节点的故障排除并不常见。如果您需要查看来自任何主节点的日志,您可以打开日志收集,将日志发送到日志分析工作区。
要在 Azure 门户中启用主节点日志收集,请导航到 AKS 资源组。不要转到具有此名称格式 MC _ resource group name _ AKS cluster name _ REGION 的 AKS 资源组。进入 AKS 资源组后,单击诊断设置。单击 AKS 集群。
图 7-16
AKS 集群的诊断设置
然后点击添加诊断设置。
图 7-17
为 AKS 集群添加诊断设置
如下图所示配置诊断设置,将日志发送到日志分析工作区。您将为诊断收集命名,选择或创建新的日志分析工作区,并选择要从中收集日志的主节点。
图 7-18
为 AKS 集群配置诊断设置
保存诊断日志设置后,您现在应该在 AKS 资源组上看到该设置,如图 7-19 所示。
图 7-19
已配置 AKS 集群的诊断设置
要查看来自 Kubernetes 主节点的实际日志,请转到您将日志发送到的日志分析工作区,并运行清单 7-24 中所示的搜索查询之一。
AzureDiagnostics
| Where Category == "kube-apiserver"
| project log_s
AzureDiagnostics
| where Category == "kube-controller-manager"
| project log_s
AzureDiagnostics
| where Category == "kube-scheduler"
| project log_s
AzureDiagnostics
| where Category == "kube-audit"
| project log_s
AzureDiagnostics
| where Category == "guard"
| project log_s
AzureDiagnostics
| where Category == "cluster-autoscaler"
| project log_s
Listing 7-24KQL queries to retrieve Kubernetes master logs
Azure Kubernetes 服务中的业务连续性和灾难恢复
在您的 AKS 群集中运行的应用将具有业务所要求的特定服务级别目标和协议(SLO 和 SLA)。作为 AKS 操作员,您的职责之一是考虑如何部署和管理 AKS,以满足这些 SLA 和 SLO。所有服务都会有这样或那样的中断,Azure Kubernetes 服务也不例外。通过了解 AKS 的底层组件以及它们如何提供服务,您可以满足或超过应用所有者的期望。
思考 SLA 和您的需求
考虑灾难恢复时,了解一些基本概念是很有用的。在灾难恢复中有一些主要的保护措施,即恢复时间目标(RTO)和恢复点目标(RPO)。RTO 定义了发生中断时恢复服务所需的时间。RPO 定义了发生此类宕机时丢失的数据量。
这两个术语都依赖于正式灾难的声明,即整个网站或服务完全不可用。还可能存在这样的情况,其中站点或服务处于降级模式,并且决定故障转移到服务的另一个站点或实例。RTO 和 RPO 是在发布灾难声明时衡量的。
在宣告失败之前,您可以确保 AKS 集群的部署方式能够防止常见的失败。让我们看看存在的各种级别的故障,以及如何使用 AKS 和 Azure 特性来防范它们。
数据持久性和复制
在 AKS 集群中运行的应用可能具有写入永久存储的有状态数据。需要考虑的一点是该存储提供的复制和保护级别。存储可能位于以下任何位置:
-
Azure VM 工作节点上的本地存储
-
Azure 托管磁盘
-
Azure 文件
-
其他 NFS 解决方案
Azure VM worker 节点上的本地存储使用 Azure 托管磁盘,持久托管磁盘卷的树内供应机制也是如此。托管磁盘仅提供本地冗余存储,这为数据中心内的驱动器故障提供保护,但不为 Azure 中的数据中心故障提供保护。Azure 文件可以配置为使用地理冗余存储,其中数据从一个 Azure 数据中心复制到另一个区域的配对数据中心。其他 NFS 解决方案可能提供不同级别的冗余。
如果应用卷上存在必须针对站点故障进行保护的持久数据,则应部署某种类型的复制或数据保护解决方案,以便在发生故障时保护这些数据。
防止故障
除了防止数据故障之外,AKS 中还可能发生许多其他故障。下面几节将回顾每一个错误和可能的缓解策略,以保护您的应用。
主节点故障
Azure Kubernetes 服务是一种托管服务,不提供对集群主节点层的可见性。如果主节点出现故障,群集将自动用新的主节点替换该主节点。作为操作员,对于主节点的故障,您几乎无能为力。
工作节点故障
作为工作节点的 Azure 虚拟机偶尔会出现错误和故障。如果某个节点出现故障,AKS 服务会用一个正常工作的节点替换该节点。然而,在一段时间内,您的运行能力会下降。对于关键群集,建议运行时具有足够的备用容量,以在不影响性能的情况下吸收单个节点的故障。
群集可以手动配置足够的节点来支持当前的性能要求,并有足够的开销来在停机期间维持性能。例如,让我们假设您有一个运行在 75%容量的四节点集群。如果一个节点丢失,其他三个节点将需要以 100%的容量运行,以符合当前的性能目标,直到第四个节点被替换。这是一种不太理想的情况。通过向群集中添加第五个节点,总体群集利用率现在将为 60%,而在停机期间,单个节点的损失将导致利用率增加到 75%。
手动配置集群大小是一个选项,但是众所周知,集群消耗是可变的。因此,更有意义的做法是监控当前利用率,并根据需要触发扩展集群的操作,或者利用当前预览中的集群自动扩展功能。
数据中心故障
Microsoft Azure 区域由多个数据中心组成。最近,许多 Azure 区域都引入了可用性区域。每个可用性区域都是一组地理上独立的资源,与同一区域的其他可用性区域有高带宽、低延迟的连接。可用性区域的目的是针对给定区域的数据中心故障提供保护。
AKS 具有预览功能,允许 AKS 群集跨越多个可用性区域。如果数据中心发生故障,假设每个可用性区域都有可用的工作节点,您的应用和 AKS 管理平面将继续不间断运行。该功能可能会在不久的将来全面推出,但是需要重新部署集群,以便将其迁移到可用性区域。目前,AKS 的数据中心中断需要像区域性故障一样处理。
区域性失败
虽然 Azure 的区域性中断非常罕见,但也不是完全没有听说过。AKS 群集不会跨区域扩展,因此问题就变成了在您的群集上运行的应用需要什么级别的保护。有几种不同的运营模式:
-
冷启动
-
标灯
-
暖星团
-
热集群
每一种都有不同的成本和回收特性。冷启动包括在另一个区域创建新的 AKS 集群。群集中应用的持久性将从备份中恢复。一旦 AKS 群集调配完毕并开始运行,并且备份恢复到适当的存储目标,应用就可以在群集上启动。这是成本最低的选项,并将具有较高的 RTO 和 RPO。
试点照明场景将包括在另一个容量减少的区域运行 AKS 集群。同样,集群中运行的应用的持久数据将从备份中恢复。在发生灾难时,群集将被扩展,备份将被恢复,应用将被部署。由于群集容量减少,这是一个低成本选项,并且仍然具有较高的 RTO 和 RPO。
暖集群场景包括在另一个已经运行应用的区域运行完全配置的 AKS 集群。某些类型的存储复制服务可能存在几分钟或几小时的延迟。恢复只需将面向公众的 DNS 条目切换到热站点。由于群集和数据复制的容量更高,这是一个成本较高的解决方案,但 RTO 和 RPO 都大大降低了。
在热集群场景中,一个完全配置的 AKS 集群在另一个区域运行,应用已经在运行并为请求提供服务。在这种情况下,存储复制解决方案需要接近同步。一个区域出现故障,只需在另一个区域上扩展集群即可处理额外的负载。这是迄今为止成本最高的解决方案,但是对于故障,RTO 和 RPO 接近于零。
每种解决方案都有其优点和缺点;因此,与额外保护的成本相比,应用所有者需要确定其应用的可接受停机时间和数据丢失量。
摘要
在 AKS 中部署应用之前,了解如何正确管理 AKS 资源很重要。AKS 集群操作员的角色是这里的关键。尽管 AKS 是一项受管理的 Kubernetes 服务,但需要提前规划一些管理操作,如扩展、身份和访问、联网、安全、监控和业务连续性规划。
在本章中,您了解了在 AKS 中经常会遇到的常见集群管理操作。我们探讨了如何正确扩展 AKS 集群,AKS 可用的存储选项,以及开始管理 AKS 集群所需的 AKS 网络、访问和身份以及安全概念。然后,我们研究了 Azure Monitor for containers 如何帮助您监控 AKS 资源。最后,我们讨论了 Azure Kubernetes 服务部署的业务连续性和灾难恢复最佳实践。
八、Azure Kubernetes 服务的 Helm 图
部署在 Kubernetes 上的应用通常由多个部分组成。一种常见的做法是将多个组件组合成一个单独的 yaml 文件,该文件将使用带有-f
开关的kubectl apply
提交给集群。跨多个环境部署同一个应用也很常见,无论这些环境是独立的 Kubernetes 集群还是同一个集群中的不同名称空间。跨多个环境使用单个 yaml 文件和kubectl
进行应用部署的方法有几个缺点。Helm 的创建就是为了解决这些缺点。
在本章中,我们将探索 Helm 的用例,以及它如何增强 Kubernetes 上的应用部署体验。我们将在开发和生产场景中回顾在 AKS 集群上安装 Helm 客户端和 Tiller 的过程。然后,我们将深入 Helm 图表的结构——Helm 中应用部署的基本构造。最后,我们将经历在 AKS 中部署和更新 Helm 图版本的过程。在本章结束时,您将对 Helm 有一个坚实的理解,以及它如何与 AKS 一起使用来简化和增强应用部署过程。
Helm 概述
Helm 是一个开源项目,由云本地计算基金会与微软、谷歌、Bitnami 等合作维护。Helm 的主要目标是帮助管理基于 Kubernetes 的应用,包括这些应用的定义、安装和升级。一个有用的方式认为 Helm 是 Kubernetes 的一个包经理。与 apt、yum 或 Chocolatey 一样,Helm 也有包含可以本地复制和安装的包的存储库——本地意思是 Kubernetes。它还可以处理这些应用的升级和删除。
Helm 用于管理 Kubernetes 应用的基本结构是 Helm 图表。该图表以标准化的格式定义了组成应用的组件,这些组件可以在源代码控制中共享和存储。当图表与配置信息结合并部署在 Kubernetes 集群上时,它被称为版本。
用例
Helm 旨在简化 Kubernetes 上的应用管理。在这方面,Helm 简化了几个主要用例。Kubernetes 应用往往由多种资源和组件组成。Helm charts 通过以声明的方式描述组件和依赖关系,帮助您管理这些应用的复杂性。
应用不是静态部署,而是定期更新。Kubernetes 上的更新过程可能会很棘手。Helm 提供了更简单的更新体验,将应用的修订和更新作为一个整体来管理,而不是作为其组成部分。新版本的图表可以包括验证测试、发布过程的定制挂钩,以及一个简单的回滚过程(如果最新的图表有问题的话)。
开发人员试图遵循“不要重复自己”的枯燥原则。Helm 将这一概念扩展到 Kubernetes 应用的部署。掌 Helm 图表可以引用其他图表以获得相关性,例如,单个 web 前端图表可以在一个环境中的多个应用中重复使用。图表的共享可以在公共或私有的存储库中进行,在 Azure Container Registry 的情况下,图表可以存储在与图表所使用的容器相同的注册表中。
优于 Kubectl
Kubectl
是管理 Kubernetes 的首选 CLI 工具,Helm 并不打算在所有活动中取代kubectl
。事实上,kubectl
通常与 Helm CLI 配合使用,用于故障排除、调查和跟踪集群中的应用部署。kubectl
和helm
都与 Kubernetes API 交互来完成他们的工作。Helm 的优势是可以使用为 Helm 编写的模板,它有几个更高级别的命令,抽象出多个kubectl
命令。例如,当使用helm install
部署应用时,Helm 软件直接与 Kubernetes API 交互,并以一种需要多个kubectl
命令的方式协调集群上的资源部署。
关键组件
为了简化 Kubernetes 应用的管理,Helm 提供了几个组成安装的关键组件。
注意
Helm 当前的主要版本是版本 2。Helm 的第 3 版正处于开发的 alpha 阶段,包含了 Helm 构建方式的几个大的变化。特别是,Tiller 组件将在版本 3 中被删除。为了本章的目的,我们将专门讨论版本 2。
Helm 客户端
Helm 客户端是用 Go 编写的二进制文件,运行在用户的本地机器上或某种 CI/CD 平台上。在那方面,它相当于kubectl
。客户端可以安装在多种操作系统上,包括 Windows、MacOS 和 Linux。最新版本的 Helm 客户端二进制文件总是可以在 Helm GitHub 发布页面上找到( https://github.com/helm/helm/releases
)。要在本地安装客户端,您可以使用 Chocolately for Windows、Homebrew for Mac 或 Snap for 某些 Linux 发行版。清单 8-1 展示了一个用 Chocolately 在 Windows 机器上安装 Helm 客户端的例子。
#Install the client
$ choco install kubernetes-helm -y
Chocolatey v0.10.3
Installing the following packages:
kubernetes-helm
By installing you accept licenses for the packages.
...
The install of kubernetes-helm was successful.
Software installed to 'C:\ProgramData\chocolatey\lib\kubernetes-helm\tools'
#Check the client version after installation
$ helm version
Client: &version.Version{SemVer:"v2.14.2", GitCommit:"a8b13cc5ab6a7dbef0a58f5061bcc7c0c61598e7", GitTreeState:"clean"}
Listing 8-1Installing the Helm client on a Windows machine
由于我们还没有配置到 Kubernetes 集群的连接,服务器版本将返回一个错误。
Helm 柄
Tiller 是 Helm 的服务器端组件,它接收 Helm 客户端发出的命令,并通过 Kubernetes API 在集群上执行这些命令。Tiller 组件通常部署在 Kubernetes 集群上,它将在那里部署应用,尽管这不是完全必要的。也可以在 Kubernetes 集群之外运行 Tiller 组件。Helm 杆部件主要负责四件事情:
-
监听来自 Helm 客户端的请求
-
将图表和配置信息部署为版本
-
在发布的整个生命周期中跟踪发布
-
从集群中升级或删除版本
Tiller 可以使用带有 RBAC 规则的服务帐户运行,这些规则定义了 Tiller 可以访问哪些名称空间。Tiller 将有能力在 Kubernetes 集群上创建和销毁应用;因此,使用角色来限制 Tiller 实例可以采取的操作是有意义的。在生产环境中,或者实际上在任何非开发环境中,Tiller 应该使用一个具有适当限制的服务帐户来控制它可以在集群中管理哪些资源。
当 Tiller 安装在集群上时,它会创建一个集群内 gRPC 端点,默认情况下该端点未经身份验证。基本上,这意味着集群中的任何进程都可以向 Tiller 端点发出命令,并执行这些命令。对于开发集群来说,这可能是可以接受的。所有其他群集环境都应该努力使用 TLS 来保护 Tiller 端点上的身份验证。当 TLS 与 Tiller 一起启用时,与 Tiller 端点的所有通信都通过可信根证书颁发机构颁发的 TLS 证书进行相互身份验证。
Helm 库
Helm 使用的图表可以存储在存储库中。存储库可以是私有的,也可以是公共的。Helm 项目在他们的 GitHub 网站( https://github.com/helm/charts
)上维护着一个官方的公共图表库。这是一个很好的起点来寻找普通应用的官方版本的掌 Helm 图,例如 Wordpress 、 FluentD 和 Jenkins 。
图表存储库只是一个 web 服务器,带有一个index.yaml
文件,该文件列出了存储在存储库中的所有图表,以及关于每个图表的一些信息。建立一个 Helm 知识库超出了本书的范围,但是这个过程相对简单,可以使用 ChartMuseum 、 GitHub Pages 或者一个简单的 web 服务器来完成。
Azure Container Registry 也能够存储 Helm 图。本章后面将给出一个使用 ACR 存储 Helm 角图的例子。
云原生应用捆绑包
云原生应用捆绑包(CNAB)是由微软和 Docker 创建的一个开源项目,用于处理应用的打包,这些应用不仅仅利用容器和 Kubernetes 进行部署。例如,一个三层 web 应用可以使用 Azure CosmosDB 提供数据库服务,使用 AKS 提供应用和 web 层,使用 Azure 函数进行业务逻辑处理。CNAB 捆绑包将能够部署和管理所有这些组件。Helm 只关注部署在 Kubernetes 环境中的应用组件。虽然形势仍在变化,CNAB 和赫尔姆完成了两个不同的,相关的目标。
安装 AKS 上的 Helm
正如在 Helm 组件一节中提到的,安装 Helm 有两个基本组件。Helm 客户端运行在本地工作站上,Tiller 服务器端组件运行在 Kubernetes 集群上。要设置 Helm 使用 AKS,需要满足几个要求。
要求
Azure Kubernetes 集群部署时默认启用了 RBAC。要让 Tiller 组件在集群上与 RBAC 一起正常工作,需要创建一个服务帐户并将其与集群角色相关联。对于非开发环境,启用 TLS 也是最佳实践。在接下来的两节中,我们将介绍设置服务帐户和提供必要证书的过程,以便在 Tiller 和 Helm 客户端之间启用 TLS 身份验证。
RBAC 和服务帐户
Kubernetes 中基于角色的访问控制包括几个不同的组件。角色定义了一组动作,被分配的实体可以对集群中的资源执行这些动作。集群有内置的角色,如集群管理、管理、编辑和查看。角色可以是两种类型之一,Role
是特定于名称空间的,ClusterRole
是集群范围的。通过使用RoleBinding
或ClusterRoleBinding
类型,可以将角色分配给服务帐户、用户和组。在清单 8-2 中,我们定义了一个用于 Tiller 的服务帐户。
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
Listing 8-2Definition for a Tiller service account
创建服务帐户后,可以为其分配角色。在清单 8-3 中,我们将使用ClusterRoleBinding
类型将 tiller 服务帐户与内置的ClusterRole
cluster-admin 关联起来。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
Listing 8-3Binding the cluster-admin role to the Tiller service account
根据环境的需求,还可以创建一个定制的Role
并使用RoleBinding
将其绑定到一个特定的名称空间,Tiller 将被允许在该名称空间中部署资源。出于我们的目的,Tiller 将被允许跨集群中的所有名称空间部署资源。在清单 8-4 中,这两个配置都已经保存到文件helm-rbac.yaml,
中,并且kubectl apply
正在将要配置 Tiller 的 AKS 集群上运行。
$ kubectl apply -f helm-rbac.yml
serviceaccount "tiller" created
clusterrolebinding.rbac.authorization.k8s.io "tiller" created
Listing 8-4Binding the cluster-admin role to the Tiller service account
Tiller 的服务帐户现在可用,并绑定到集群管理角色。
TLS 注意事项
部署完整的公钥基础设施(PKI)超出了本书的范围。事实上,整本书都是关于这个话题的。如果您的组织已经建立了内部 PKI,那么利用它是有意义的。在下面的例子中,我们将使用openssl
来创建证书。这里有三个证书:根证书颁发机构、tiller 证书和 helm 客户端证书。tiller 和 helm 客户端证书将由根 CA 证书批准和签名,Tiller 和 Helm 将被配置为信任根 CA 证书。由于他们都信任根 CA,他们将信任由根 CA 签署的证书,这意味着 Tiller 和 Helm 将信任彼此的证书是有效的。
清单 8-5 中的所有命令将在当前工作目录中创建证书和密钥。
#First we must create the root CA.
#Big thanks to this article: https://medium.com/google-cloud/install-secure-helm-in-gke-254d520061f7
$SUBJECT = "/C=US/ST=Pennsylvania/L=Springfield/O=IAKS, Inc./OU=IT/CN=iaks.sh"
#Create a CA key
openssl genrsa -out ca.key.pem 4096
#Creata a CA certificate
openssl req -key ca.key.pem -new -x509 -days 7300 -sha256 -out ca.cert.pem -extensions v3_ca -subj $SUBJECT
#Then we need to create the certificate request for the Tiller certificate and process it.
#Create a key for the tiller cert
openssl genrsa -out tiller.key.pem 4096
#Create a new certificate request
openssl req -new -sha256 -key tiller.key.pem -out tiller.csr.pem -subj $SUBJECT
#Create the certificate from the request
openssl x509 -req -days 365 -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in tiller.csr.pem -out tiller.cert.pem
#Finally, we need to create the certificate request for the Helm client certificate and process it.
#Create a key for the helm client
openssl genrsa -out helm.key.pem 4096
#Create a new certificate request
openssl req -new -sha256 -key helm.key.pem -out helm.csr.pem -subj $SUBJECT
#Create the certificate from the request
openssl x509 -req -days 365 -CA ca.cert.pem -CAkey ca.key.pem -CAcreateserial -in helm.csr.pem -out helm.cert.pem
Listing 8-5Creating TLS certificates for Tiller and Helm communication
现在我们有了所有必需的证书和它们匹配的私钥。在当前目录中,我们应该看到清单 8-6 中的文件。
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 7/16/2019 1:39 PM 2070 ca.cert.pem
-a---- 7/16/2019 1:39 PM 3298 ca.key.pem
-a---- 7/16/2019 1:40 PM 18 ca.srl
-a---- 7/16/2019 1:40 PM 1946 helm.cert.pem
-a---- 7/16/2019 1:40 PM 1736 helm.csr.pem
-a---- 7/16/2019 1:40 PM 3298 helm.key.pem
-a---- 7/16/2019 1:40 PM 1946 tiller.cert.pem
-a---- 7/16/2019 1:40 PM 1736 tiller.csr.pem
-a---- 7/16/2019 1:39 PM 3294 tiller.key.pem
Listing 8-6Directory listing of TLS certificates and private keys
将使用 Helm 客户端进行连接的每个用户都应该获得他们自己的证书,包括在 CI/CD 流水线中运行的任何自动化帐户。在生产场景中,证书的颁发将通过证书颁发机构来处理。虽然可以使用第三方证书颁发机构,但在这种情况下,内部 CA 更有意义。Kubernetes 集群可能会使用内部名称,并由内部用户访问。没有必要花钱购买可信第三方的证书。
init 头盔
一旦 Tiller 安装的先决条件得到满足,下一步就是运行命令helm init
来初始化集群。在开发环境中,只需使用命令暗示的所有默认值运行helm init
就足够了。因为我们将使用服务帐户和证书,所以我们需要给helm init
命令添加参数。
清单 8-7 中的命令使用 tiller 服务帐户,并安装 tiller 私钥、证书和根 CA 证书。此外,Tiller 的证书信息默认保存在ConfigMap
中。由于信息的敏感性,最佳实践是覆盖默认设置,而使用一个Secret
类型的资源来保存数据。
$ helm init /
--override 'spec.template.spec.containers[0].command={/tiller,--storage=secret}' /
--tiller-tls /
--tiller-tls-cert ".\tiller.cert.pem" /
--tiller-tls-key ".\tiller.key.pem" /
--tiller-tls-verify /
--tls-ca-cert ".\ca.cert.pem" /
--service-account tiller
Listing 8-7Initializing Tiller on the AKS cluster
蒂勒是作为一个部署安装在 Kubernetes。默认情况下,它在一个副本集中运行一个 pod,并包含一个与ClusterIP
相关联的服务。pod 和服务都在清单 8-8 中进行了描述。
$ kubectl describe pod tiller-deploy-6656966795-7sxqx --namespace kube-system
Name: tiller-deploy-6656966795-7sxqx
Namespace: kube-system
Priority: 0
PriorityClassName: <none>
Node: aks-agentpool-28083664-0/10.240.0.4
Start Time: Tue, 16 Jul 2019 14:01:20 -0400
Labels: app=helm
name=tiller
pod-template-hash=6656966795
Annotations: <none>
Status: Running
IP: 10.244.0.8
Controlled By: ReplicaSet/tiller-deploy-6656966795
Containers:
tiller:
Container ID: docker://fd05f519da5911b07e0d2aa476b0c9661fe3181ee63a043ca5188eb675bbb64b
Image: gcr.io/kubernetes-helm/tiller:v2.14.2
Image ID: docker-pullable://gcr.io/kubernetes-helm/tiller@sha256:be79aff05025bd736f027eaf4a1b2716ac1e09b88e0e9493c962642519f19d9c
Ports: 44134/TCP, 44135/TCP
Host Ports: 0/TCP, 0/TCP
Command:
/tiller
--storage=secret
State: Running
Started: Tue, 16 Jul 2019 14:01:32 -0400
Ready: True
Restart Count: 0
Liveness: http-get http://:44135/liveness delay=1s timeout=1s period=10s #success=1 #failure=3
Readiness: http-get http://:44135/readiness delay=1s timeout=1s period=10s #success=1 #failure=3
Environment:
TILLER_NAMESPACE: kube-system
TILLER_HISTORY_MAX: 0
TILLER_TLS_VERIFY: 1
TILLER_TLS_ENABLE: 1
TILLER_TLS_CERTS: /etc/certs
Mounts:
/etc/certs from tiller-certs (ro)
/var/run/secrets/kubernetes.io/serviceaccount from tiller-token-2dbcn (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
tiller-certs:
Type: Secret (a volume populated by a Secret)
SecretName: tiller-secret
Optional: false
tiller-token-2dbcn:
Type: Secret (a volume populated by a Secret)
SecretName: tiller-token-2dbcn
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
$ kubectl describe svc tiller-deploy --namespace kube-system
Name: tiller-deploy
Namespace: kube-system
Labels: app=helm
name=tiller
Annotations: <none>
Selector: app=helm,name=tiller
Type: ClusterIP
IP: 10.0.84.117
Port: tiller 44134/TCP
TargetPort: tiller/TCP
Endpoints: 10.244.0.8:44134
Session Affinity: None
Events: <none>
Listing 8-8Tiller pod and service details
运行初始化后,可以通过运行清单 8-9 中的命令来测试从 Helm 客户端到 Tiller 的连接。
$ helm version --tls --tls-ca-cert ca.cert.pem /
--tls-cert helm.cert.pem --tls-key helm.key.pem
Client: &version.Version{SemVer:"v2.14.2", GitCommit:"a8b13cc5ab6a7dbef0a58f5061bcc7c0c61598e7", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.2", GitCommit:"a8b13cc5ab6a7dbef0a58f5061bcc7c0c61598e7", GitTreeState:"clean"}
Listing 8-9Testing helm client connectivity to Tiller
在该命令中,我们指定我们想要使用 TLS,并且还传递了 CA 证书、 helm 客户端证书和 helm 客户端密钥。显然,我们不想在每次运行 helm 命令时都指定这些选项。当使用--tls
标志时,helm 客户端将在用户主目录的.helm
目录中查找 TLS 文件。清单 8-10 中的命令会将文件复制到正确的路径,并提供 helm 客户端所需的文件名。
copy ca.cert.pem "~\.helm\ca.pem"
copy helm.cert.pem "~\.helm\cert.pem"
copy helm.key.pem "~\.helm\key.pem"
Listing 8-10Copying
the helm TLS certs and keys to the .helm directory
复制这些文件后,只需在运行 helm 客户端命令时指定--tls
。如果命令中没有设置--tls
标志,那么 helm 客户端将会无限期挂起。
Helm 柄服务启动并运行,准备接受 Helm 柄命令。现在是时候构建一个图表提交给 Tiller 了。
头盔图表
Helm 图表是 Helm 用来部署应用的基本结构。该图表与配置设置相结合,并提交给 Tiller。Tiller 将把图表和设置合成到一个版本中,并在 Kubernetes 集群上提供该版本。图表是文件和目录的明确集合。有些文件和目录是必需的,比如Chart.yaml
文件。根据图表,其他文件和目录是可选的。
在本章的剩余部分,我们将引用一个名为 iaks 的现有图表,该图表部署了一个投票应用,它具有 node.js 前端和 redis 后端。
图表内容
清单 8-11 显示了 Helm 图表的标准文件和文件夹结构。所需文件以粗体显示。
ChartName (parent directory)
Listing 8-11Standard chart file and folder structure
-
Chart.yaml :包含关于图表的信息
-
许可证:图表的人类可读许可证
-
README.md:人类可读的降价文件
-
requirements.yaml:图表依赖列表
-
values.yaml :图表的默认配置值
-
图表:该图表所依赖的图表目录
-
模板:模板目录
-
templates/NOTES.txt:带有用法说明的可读文件
虽然图表和模板目录不是必需的,但它们是保留给 Helm 使用的。添加到图表中的任何其他文件都将包括在内,但不一定有任何特殊意义。
清单 8-12 显示了 iaks 图表的结构。
C:.
│ .helmignore
│ Chart.yaml
│ values.yaml
│
└───templates
NOTES.txt
vote-back-deployment.yaml
vote-back-service.yaml
vote-front-deployment.yaml
vote-front-service.yaml
Listing 8-12iaks chart structure
图表. yaml
Chart.yaml
文件定义了 Helm 将用来解释图表的值。列表 8-13 包含潜在的文件条目,所需条目以粗体显示。
-
apiVersion :现在总是设置为 v1
-
名称:图表的名称
-
版本:该图表的 SemVer 2 版本
-
kubeversion:永远范围相容于 kubeversion
-
描述:描述图表及其目的的单句话
-
关键词:关键词列表
-
主页:项目主页 URL
-
来源:项目的源代码 URL
-
维护者:项目维护者的列表
-
引擎:模板引擎的名称(默认为 gotpl)
-
icon: SVG or PNG 影像网址
-
appVersion:应用的版本号
-
已弃用:布尔值,指示图表是否已弃用
-
tillerVersion:兼容 Tiller 版本的永久范围
file entries
Listing 8-13Chart.yaml
清单 8-14 显示了 iaks 图表的Chart.yaml
文件的内容。
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for deploying the IAKS Voting App
name: iaks
version: 0.1.0
Listing 8-14iaks Chart.yaml contents
请注意,appVersion
和version
条目并不相同。图表的版本可能会改变,但应用的版本不会改变。
价值观. yaml
values.yaml
文件定义了项目中图表和模板使用的默认设置。所有图表和模板都可以访问顶层values.yaml
文件中定义的设置。也可以在模板和图表子目录中提供values.yaml
文件。在部署图表时,可以通过提供一个额外的带有值的 yaml 文件或者使用--set
标志并在命令行提供设置来覆盖Values.yaml
文件中定义的设置。
模板和图表将通过使用名称空间样式引用符号来引用在values.yaml
中定义的设置。名称空间以代表名称空间顶部的.
开始,然后其他字符串向下钻取文件中的值。例如,values.yaml 文件可能有一个类似于清单 8-15 中的条目。
image:
repository: iaks/azure-voting-app
tag: v1-alpine
Listing 8-15Example values.yaml snippet
模板将通过使用符号.Values.image.tag
来引用标签。
除了文件或命令行提供的值之外,图表和模板还可以访问预定义的值。这些包括关于版本、图表和文件的信息。Helm 文档中提供了预定义值的详尽列表。
清单 8-16 显示了 iaks 图表的values.yaml
文件的内容。
# Default values for iaks.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
voteBack:
replicaCount: 1
appName: azure-vote-back
image:
repository: redis
tag: 5.0.5
pullPolicy: IfNotPresent
ports:
name: redis
port: 6379
service:
port: 6379
voteFront:
replicaCount: 1
appName: azure-vote-front
image:
repository: iaks/azure-voting-app
tag: v1-alpine
pullPolicy: IfNotPresent
ports:
name: http
port: 80
vote1Value: "Chocolate"
vote2Value: "Peanut Butter"
title: "IAKS Voting App"
service:
type: LoadBalancer
port: 80
targetPort: http
name: http
Listing 8-16iaks values.yaml contents
许可证
LICENSE
文件是以纯文本格式编写的,旨在展示图表中安装的应用所包含的软件许可证。Helm 客户端不读取许可证。如果用户选择使用图表,它就在那里供用户解析和默认。
iaks 图表没有许可证文件。
README.md
README.md
是用 markdown 写的,旨在帮助用户正确使用图表。至少,它应该描述图表的作用、运行图表的先决条件、包含在values.yaml
文件中的设置以及默认设置。本文档中还应包含部署图表的任何其他有用信息。如果图表在某些存储库上发布,将显示README
文件。
如果有一些快速入门说明需要在部署后显示给用户,它们可以包含在模板目录下的NOTES.txt
文件中。NOTES.txt
文件将被评估为模板,然后显示在命令行上。
清单 8-17 显示了从 iaks 图表README.md
中截取的文本。
# IAKS Voting App
Example application for the Helm chapter of the Introducing Azure Kubernetes Service book.
## Install Chart
To install the IAKS Chart into your Kubernetes cluster :
Clone the chart down to your local file system.
```bash
helm install --namespace "iaks" --name "iaksv1" ./iaks
...
Listing 8-17iaks README.md contents
#### 需求. yaml
正在定义的图表可能使用其他图表作为其部署的一部分。这些图表可以手动复制到*图表*目录并保存在那里。对于需要严格控制依赖图表的版本和内容的团队来说,将它们直接复制到*图表*目录中可能是有意义的。但是,这使得图表是静态的,需要手动更新。
当运行`helm dependency update`命令时,包含在`requirements.yaml`文件中的图表被动态提取。由此产生的图表以压缩图表的形式存储在*图表*目录中。在 requirements.yaml 文件中,每个图表都在依赖关系中列出,如清单 8-18 所示。
dependencies:
- name: chart_name
version: 1.2.3
repository: http://mycharts.com/charts
Listing 8-18Example requirements.yaml entry
当新版本可用时,可以在依赖关系中更新版本号,并再次运行`helm dependency update`命令。这将提取图表的新版本,并将其存储在*图表*目录中。
有几个附加的可选字段可以添加到依赖项列表中。这些可选字段用于更高级的部署情况,您可能在初次尝试使用 Helm 时不需要它们。
如果一个应用需要同一图表的多个副本,或者同一图表的不同版本,可以包括的`alias`字段。`alias`字段将改变下载图表的名称以匹配别名值。
`condition`字段指定了顶层父`values.yaml`中的 *yaml* 实体的逗号分隔列表,每个实体解析为一个布尔值。将该值设置为`false`将阻止图表作为依赖项包含在图表中。
`tags`字段是与图表相关联的标签列表。在顶层父值中,可以使用标签和一个布尔值来启用或禁用每个`tag`。如果某个依赖图表的任何`tag`被启用,它将被包括在依赖关系中。
**iaks** 图表没有 requirements.yaml 文件。
#### 图表目录
*图表*目录将包含要作为父图表的依赖项包含的图表。正如 Requirements.yaml 一节中提到的,图表可以通过手动复制文件来填充,或者通过使用`requirements.yaml`文件来动态填充。包含在*图表*目录中的图表可以是未打包的图表,也可以是图表档案。如果使用归档文件,每个图表应该是它自己单独的文件;如果图表被解压缩,每个图表应该是它自己的目录。
**iaks** 图表不使用任何其他图表作为依赖项。
#### 模板目录
*模板*目录包含 Helm 图模板。当 Helm 为一个版本渲染图表时,它会评估包含在*模板*文件夹中的所有文件。模板文件的大部分功能都使用 Go 模板语言。Helm 还借用了 Sprig 库中的一些函数,包括一些 Helm 特有的特殊函数。
*模板*目录中的文件用于在 yaml 中创建可行的 Kubernetes 定义文件。模板语言用于操作文件内容,动态生成有效的 yaml 文件,合并由`values.yaml`文件提供的值或由用户在运行`helm install`时提供的值。
**iaks** 图表有前端和后端部署和服务的模板,以及一个`NOTES.txt`。我们将在处理模板函数的部分更详细地检查这些文件。
### 图表存储库
Helm 处理存储在存储库中的图表。helm 客户端有一个命令子集,用于处理本地存储的图表和远程存储库。让我们从查看默认安装的 Helm 中可用的图表库列表开始,如清单 8-19 所示。
$ helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com
local http://127.0.0.1:8879/charts
incubator http://storage.googleapis.com/kubernetes-charts-incubator
Listing 8-19Listing of Helm repositories
如你所见,Helm 从官方 Helm 库的*马厩*和*孵化器*图表开始。它还创建了一个监听端口 8879 的本地存储库。默认情况下,*本地*存储库没有图表。我们可以通过运行清单 8-20 中的命令来确认这一点。
$ helm search /local
No results found
Listing 8-20Contents of the local repository
对清单 8-21 中所示的*稳定*库运行相同的命令会产生大约 278 个图表!
$ helm search stable/
NAME CHART VERSION APP VERSION DESCRIPTION
stable/acs-engine-autoscaler 2.2.2 2.1.1 DEPRECATED Scales worker nodes within agent pools
stable/aerospike 0.2.7 v4.5.0.5 A Helm chart for Aerospike in Kubernetes
stable/airflow 2.8.2 1.10.2 Airflow is a platform to programmatically author, schedul...
Listing 8-21Contents of the stable repository
图表列表缓存在本地。要更新存储库的内容,可以执行命令`helm repo update`。将图表打包并推送到存储库的过程将在本章的后面介绍。
### 部署流程
将 Helm chart 部署为 Kubernetes 集群上的运行应用是通过命令`helm install`执行的。install 命令允许以附加 yaml 文件的形式或使用命令中的`--set`标志提交值。运行时提交的值中的设置与图表中的`values.yaml`文件合并,生成一个更新的`values.yaml`文件,其中包含将在安装过程中使用的最终配置数据。
例如,假设`helm install -f myvalues.yaml ./mychart`正在运行。图表中已有的`values.yaml`文件的内容如清单 8-22 所示。
voteBack:
replicaCount: 1
appName: azure-vote-back
image:
repository: redis
tag: 5.0.5
pullPolicy: IfNotPresent
ports:
name: redis
port: 6379
Listing 8-22values.yaml file with default configuration
myvalues.yaml 文件的内容如清单 8-23 所示。
voteBack:
replicaCount: 2
label: mylabel
Listing 8-23Contents of myvalues.yaml
这两个文件将合并在一起,`myvalues.yaml`文件的内容优先于`values.yaml`文件的内容。清单 8-24 有结果文件的内容。
voteBack:
replicaCount: 2
label: mylabel
appName: azure-vote-back
image:
repository: redis
tag: 5.0.5
pullPolicy: IfNotPresent
ports:
name: redis
port: 6379
Listing 8-24Contents of the new values.yaml file
Tiller 接受图表和值,并创建一组有效的 Kubernetes 定义,这些定义通过 Kubernetes API 提交给集群。按照 Helm 的说法,提交的部署被称为*发布*。
Helm 版本包含几条描述版本的信息,包括以下内容:
* **AppVersion** :基于 Chart.yaml 中 AppVersion 设置的版本号
* **图表**:Chart . YAML 中附加版本号的图表名称
* **Name** :安装时给版本起的名字
* **名称空间**:安装该版本的名称空间
* **修订版**:第一次安装时从 1 开始,每次执行更新或回滚时递增
* **状态**:版本的当前状态,通常为已经完成安装的版本部署
* **更新**:最后一次版本的某些方面发生变化
可以通过运行`helm list`或缩短版本`helm ls`来检索当前的发布列表。默认情况下,该命令只显示状态为`DEPLOYED`的版本。可以添加标志`--all`来查看任何状态的所有发布。
可以使用以下命令之一更新 Helm 版本:
* `helm delete`:从集群中删除发布,并将发布状态更改为已删除
* `helm upgrade`:用提交的值升级当前版本
* `helm rollback`:将当前版本恢复为提交的修订号
### 创建 Helm 图
有许多优秀的图表已经可以作为创建自己的 Helm 图的起点。Helm 还包括从预定义模板开始绘制图表的工具。
#### 掌 Helm 创建
Helm 使为新图表设置文件和目录结构变得简单。`helm create`命令将在指定的路径下创建一个新的目录,并在该目录下创建几个 Helm 图的必需和可选文件。命令`helm create iaks-chart`将创建一个名为 iaks-chart 的新 Helm 图。
该命令在当前路径中创建一个名为 iaks-chart 的目录,并用清单 8-25 中所示的文件和目录填充它。
C:.
│ .helmignore
│ Chart.yaml
│ values.yaml
│
├───charts
└───templates
│ deployment.yaml
│ ingress.yaml
│ NOTES.txt
│ service.yaml
│ _helpers.tpl
│
└───tests
test-connection.yaml
Listing 8-25Contents of the new iaks-chart Helm chart
这些文件包含一个基本的 *nginx* 应用,包括一个入口控制器,一个用于*nginx*pod 的服务,以及一个*nginx*pod 的部署。它还包括一个测试来验证 *nginx* 应用的部署是否成功。
#### 模板功能
helm 图表中的模板结合使用了 Go 模板语言函数、Sprig 函数和 Helm 中的自定义函数。这些函数获取模板文件的内容和安装期间提交的值,并呈现出有效的 Kubernetes 定义。
Go 模板语言是一个高级主题,超出了本章的范围,但是这里有一些入门的指导。
* 模板文件中应该由模板引擎评估的任何值都将以双花括号{{ }}开始和结束。
* value.yaml 文件中的值使用命名空间路径表示法引用,例如. Values.dockerTag。
* Helm 有一本关于模板开发入门的入门书。你可以在这个链接了解更多( [`https://helm.sh/docs/chart_template_guide/#getting-started-with-a-chart-template`](https://helm.sh/docs/chart_template_guide/%2523getting-started-with-a-chart-template) )。
看一个例子将有助于说明模板语言是如何使用的。清单 8-26 显示了 **iaks** 图表中`vote-back-service.yaml`文件的内容。
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.voteBack.appName }}
spec:
ports:
- port: {{ .Values.voteBack.service.port }}
selector:
app: {{ .Values.voteBack.appName }}
Listing 8-26Contents of the new vote-back-service.yaml file
`{{ }}`调用模板引擎来评估双花括号中的内容。在清单中,`metadata.name`正在评估表达式`.Values.voteBack.appName`。指的是发布提交的`values.yaml`文件中的设置。该设置的默认设置是 *azure-vote-back* ,因此模板引擎将呈现文件的这一部分,如清单 8-27 所示。
metadata:
name: azure-vote-back
Listing 8-27Rendered value for metadata.name
可以将函数添加到流水线中的评估中,以操作该值。例如,假设名称需要全部小写。清单 8-28 展示了如何通过流水线将值传递给`lower`来操作文本。
metadata:
name: {{ .Values.voteBack.appName | lower }}
Listing 8-28Using the lower function on a value
这是一个使用模板函数的简单例子。根据应用的需要,更复杂的评估是可能的。
#### 图表测试
Helm 不知道图表中定义的应用应该做什么。如果发布的所有组件都创建成功,那么 Helm 认为发布是成功的。图表测试为用户提供了一种验证应用组件功能是否正常的方法。它们也可以在自动化环境中使用,以验证流水线中的发布。
图表测试是驻留在*模板*目录中的模板文件,或者更常见的是驻留在*模板*目录中的*测试*子目录中。每个测试都是一个 *pod* 定义。pod 应该运行一些操作,然后以一个值退出,`0`被认为是成功,任何其他值被认为是失败。pod 定义可以是单个 *yaml* 文件的一部分,也可以分成多个 *yaml* 文件,每个测试一个。
Helm 有两个指示测试是否成功的测试挂钩,`test-success`和`test-failure`。这些钩子被添加到吊舱的注释中,如清单 8-29 所示。
metadata:
annotations:
"helm.sh/hook": test-success
Listing 8-29Helm test hooks
注释向 Helm 表明这些 pod 定义是测试,而不是应用的一部分。通过使用要测试的发布名称运行`helm test`来调用测试。
#### 打包图表
一旦图表可供使用,就可以打包并上传到图表存储库中。打包图表会创建该图表的版本化存档。图表的内容被压缩成一个 tgz 文件。可以通过使用`helm package`命令并将该命令指向包含图表的目录来打包图表。
清单 8-30 显示了包装 **iaks** 图表的过程。
$ helm package .\iaks
Successfully packaged chart and saved it to: C:\gh\Introducing-Azure-Kubernetes-Service\Helm\aks\iaks-0.1.0.tgz
Listing 8-30Packaging the iaks chart
文件的名称是图表名称和图表版本的组合。这两个值都可以在`Chart.yaml`文件中找到。
将图表存档上传到存储库的过程将取决于存储库的类型。上传图表时,必须更新存储库的 index.yaml 文件,以便将它包含在存储库搜索和列表中。Azure Container Registry (ACR)可以托管打包的 helm 图表。第一步是登录到一个现有的 ACR 存储库,并将其添加为 Helm 的存储库,如清单 8-31 所示。
$ az acr login --name iaks0
$ az acr helm repo add
"iaks0" has been added to your repositories
$ helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com
local http://127.0.0.1:8879/charts
incubator http://storage.googleapis.com/kubernetes-charts-incubator
iaks0 https://iaks0.azurecr.io/helm/v1/repo
Listing 8-31Adding the ACR repo to Helm
一旦存储库被添加到 Helm 中,将图表存档推送到 ACR 存储库就很简单了,如清单 8-32 所示。然后,必须更新存储库的本地索引,以便它将显示在搜索结果中。
$ az acr helm push .\iaks-0.1.0.tgz
{
"saved": true
}
$helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "incubator" chart repository
...Successfully got an update from the "iaks0" chart repository
...Successfully got an update from the "stable" chart repository
Update Complete.
$ helm search iaks0
NAME CHART VERSION APP VERSION DESCRIPTION
iaks0/iaks 0.1.0 1.0 A Helm chart for deploying the IAKS Voting App
Listing 8-32Pushing a package to the ACR repo
图表存档现在可供任何其他具有访问权限的用户通过 ACR 存储库使用。
### 部署 Helm 图
使用`helm install`命令展开 Helm 图。该命令将获取图表、默认值和命令中提交的值,并将它们发送给 Tiller。Tiller 会将它们合成为一个版本,并在 Kubernetes 集群上实例化该版本。
#### Helm 安装
清单 8-33 显示了在 aks 集群的*默认*名称空间中安装 **iaks** 图表的过程。
$ helm install --tls --name iaksv1 ./iaks
NAME: iaksv1
LAST DEPLOYED: Wed Jul 17 11:40:30 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
azure-vote-back-78d97d47df-2hjbr 0/1 ContainerCreating 0 0s
azure-vote-front-948444d79-m2ms2 0/1 ContainerCreating 0 0s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
azure-vote-back ClusterIP 10.0.40.25
azure-vote-front LoadBalancer 10.0.212.114
==> v1beta1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
azure-vote-back 0/1 1 0 0s
azure-vote-front 0/1 1 0 0s
NOTES:
1. Get the application URL by running these commands:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace default svc -w azure-vote-front'
export SERVICE_IP=\((kubectl get svc --namespace default azure-vote-front -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://\)SERVICE_IP:80
Listing 8-33Installing the iaks chart
安装过程显示正在创建的资源,并打印出 templates 文件夹中呈现的`NOTES.txt`文件。`NOTES.txt`文件由模板引擎评估,可以为应用的开始提供简单的指导。
图 8-1 显示了负载均衡器的外部 IP 完成配置后可用的网页。
![img/484429_1_En_8_Fig1_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_8_Fig1_HTML.jpg)
图 8-1
投票应用网页
#### 掌 Helm 状态
命令`helm` `status`将获得一个发布的当前状态。清单 8-34 显示了 *iaksv1* 版本的当前状态。
$ helm status --tls iaksv1
LAST DEPLOYED: Wed Jul 17 11:40:30 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
azure-vote-back-78d97d47df-2hjbr 1/1 Running 0 4m36s
azure-vote-front-948444d79-m2ms2 1/1 Running 0 4m36s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
azure-vote-back ClusterIP 10.0.40.25
azure-vote-front LoadBalancer 10.0.212.114 40.85.173.41 80:30829/TCP 4m36s
==> v1beta1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
azure-vote-back 1/1 1 1 4m36s
azure-vote-front 1/1 1 1 4m36s
NOTES:
1. Get the application URL by running these commands:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace default svc -w azure-vote-front'
export SERVICE_IP=\((kubectl get svc --namespace default azure-vote-front -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo http://\)SERVICE_IP:80
Listing 8-34Status of the iaksv1 release
该状态提供了与初始安装基本相同的信息,包括`NOTES.txt`部分。
### 更新版本
在版本的生命周期中,可能需要更新图表、应用或设置。命令`helm upgrade`用于执行这样的更新。清单 8-35 显示了用投票按钮的新值更新 *iaksv1* 版本的过程。
$ helm upgrade --tls --set voteFront.vote1Value=Cats,voteFront.vote2Value=Dogs iaksv1 ./iaks
Release "iaksv1" has been upgraded.
LAST DEPLOYED: Wed Jul 17 11:50:14 2019
Listing 8-35Upgrade of the iaksv1 release
为简洁起见,输出被截断。通过运行清单 8-36 中的`helm ls`,我们可以检索发布的状态,并看到修订号已经增加。
$ helm ls --tls iaksv1
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
iaksv1 2 Wed Jul 17 11:50:14 2019 DEPLOYED iaks-0.1.0 1.0 default
Listing 8-36Listing of the iaksv1 release
查看图 8-2 中更新的网页,显示按钮的更新内容。
![img/484429_1_En_8_Fig2_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_8_Fig2_HTML.jpg)
图 8-2
投票应用网页已更新
也可以通过使用`helm rollback`命令回滚到先前版本。清单 8-37 显示了回滚一个发布的输出。
$ helm rollback --tls iaksv1 1
Rollback was a success.
$ helm ls --tls iaksv1
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
iaksv1 3 Wed Jul 17 11:54:45 2019 DEPLOYED iaks-0.1.0 1.0 default
Listing 8-37Rollback of the iaksv1 release
通过查看版本的修订号,我们可以看到修订现在是在`3`而不是`1`。无论版本是升级还是回滚,版本号都会随着版本的改变而增加。
再次查看图 8-3 中的网站,我们可以看到投票按钮已经恢复到之前的值。
![img/484429_1_En_8_Fig3_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_8_Fig3_HTML.jpg)
图 8-3
投票应用网页回滚
### 删除版本
在每个版本的生命周期中都有一个不再需要它的时候。删除发布的命令是`helm delete`。清单 8-38 显示了删除 iaksv1 的输出。
$ helm delete --tls iaksv1
release "iaksv1" deleted
Listing 8-38Delete of the iaksv1 release
Kubernetes 集群中的资源将被移除,但是发布版并没有完全消失。清单 8-39 显示了所有的版本,包括被删除的版本。
$ helm ls --tls --all
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
iaksv1 3 Wed Jul 17 11:54:45 2019 DELETED iaks-0.1.0 1.0 default
Listing 8-39Listing of all releases
可以使用`helm rollback`来撤销从 Kubernetes 集群中删除发布。
### 注意
Helm 不会从删除的版本中恢复确切的 pod 和卷。Helm 将只重新部署 rollback 命令中指定的版本。在删除一个版本的过程中,任何没有通过其他方式保存的数据都将丢失。
为了从 Helm 杆上永久移除释放,必须使用清单 8-40 中所示的`--purge`标志。
$ helm delete --tls iaksv1 --purge
release "iaksv1" deleted
Listing 8-40Purge of the iaksv1 release
## CI/CD 集成
持续集成和持续交付——通常缩写为 CI/CD——是创建自动化流水线的实践,该流水线将代码从开发人员的提交移动到部署到一个或多个环境中。Helm 可以整合到 CI/CD 流程中,作为一种工具,用于向 Kubernetes 集群部署新版本或更新现有版本。
### 自动化部署
当代码被提交到存储库时,它可能会引发一系列事件。使用我们的 **iaks** 图表示例,该图表利用了容器映像 *iaks/azure-voting-app。*当开发人员提交构建该映像的`Dockerfile`的新版本时,可能会触发一个流水线。一旦映像被更新并通过流水线中的必要测试, **iaks** Helm 图可以用新的映像版本进行测试。假设所有的测试都通过了, **iaks** Helm chart 可以被更新以使用新的映像作为`values.yaml`文件中的默认标签。
图 8-4 展示了潜在的流水线。
![img/484429_1_En_8_Fig4_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_8_Fig4_HTML.jpg)
图 8-4
潜在的 CI/CD 渠道
### 测试 Helm 图
Helm 图可以用几种方法测试。可以使用`helm lint`命令运行一个测试来验证图表在语法上是正确的。清单 8-41 显示了对照 **iaks** 图表运行`helm lint`的输出。
$ helm lint .\iaks
==> Linting .\iaks
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, no failures
Listing 8-41Linting the iaks chart
输出应该是人类可读的,但是在将图表转移到下一个测试阶段之前,它可以被机器解析以查看是否有任何错误或警告。
下一个测试步骤可能是用几个不同的可能值在本地呈现模板,并验证生成的 Kubernetes 定义是有效的。清单 8-42 显示了针对 iaks 图表中的模板运行`helm template`的输出。为简洁起见,输出被截断。
helm template .\iaks\
Source: iaks/templates/vote-back-service.yaml
apiVersion: v1
kind: Service
metadata:
name: azure-vote-back
spec:
ports:
- port: 6379
selector:
app: azure-vote-back
Listing 8-42Helm template rendering
这个命令的输出可以通过流水线传输到`kubectl`来验证内容。
$ helm template .\iaks | kubectl apply --dry-run --validate -f -
可以对输出进行错误扫描,以确定是否有任何 Kubernetes 定义无效。
一旦图表根据需求得到验证,就可以对其进行进一步的测试,以验证应用是否正常运行。一些测试可以使用本章前面提到的 Helm 测试功能嵌入到图表中。除了 Helm 执行的基本测试之外,大多数自动化流水线还会对应用执行额外的测试。Helm 图中包含的测试旨在测试基本功能,而不是更高级的场景。
有一个与 Helm 相关的开源项目,专门围绕测试 Helm 图。这个项目叫做*图表测试*,可以在 GitHub ( [`https://github.com/helm/chart-testing`](https://github.com/helm/chart-testing) )上找到。*图表测试*软件能够执行林挺、模板验证,甚至可以针对某个版本运行图表中包含的 Helm 测试。
### 无人值守 Helm 图安装
在 Kubernetes 集群上安装 Helm 图可以以自动化的方式执行。用于定制给定版本的值可以作为 CI/CD 流水线中的工件生成,然后作为文件或通过`--set`标志传递给 Helm 客户端。
相同的过程可用于执行现有版本的升级,包括随后运行 Helm 测试,并准备在测试失败或发现其他问题时运行回滚操作。流水线应在升级前记录 Helm 版本的当前修订号,以便在必要时协助回滚过程。
### 将 Helm 与 Azure DevOps 集成
Azure DevOps (ADO)有许多与 Helm 集成的服务来帮助自动化开发流水线。ADO 中的 Repos 可以作为 Helm 图开发时的源控件。*工件*可以用来存储生成的数值进行 Helm 释放。*流水线*可用于建立 CI/CD 流水线,该流水线使用 Helm 在 AKS 集群上部署发布。
Azure DevOps 的*流水线*部分包括多个任务,支持将 Helm 用于 AKS 服务。 *Helm 工具安装程序*任务将在运行作业的代理机器上安装 Helm 二进制文件。*打包和部署 Helm charts* 任务允许运行基本上任何 Helm 客户端命令,包括使用 TLS 认证的选项。该任务以 AKS 集群为目标,使得在 AKS 集群上安装 Helm 图表相对简单。清单 8-43 展示了 Azure DevOps 中的示例 *yaml* 构建流水线。
Helm deployment pipeline
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
steps:
-
task: HelmInstaller@1
inputs:
helmVersionToInstall: 'latest' -
task: DownloadSecureFile@1
inputs:
secureFile: 'ca.cert.pem' -
task: DownloadSecureFile@1
inputs:
secureFile: 'helm.cert.pem' -
task: DownloadSecureFile@1
inputs:
secureFile: 'helm.key.pem' -
task: HelmDeploy@0
inputs:
connectionType: 'Azure Resource Manager'
azureSubscription: 'MAS(4d8e572a-3214-40e9-a26f-8f71ecd24e0d)'
azureResourceGroup: 'iaks'
kubernetesCluster: 'iaks1'
namespace: 'iaks'
command: 'install'
chartType: 'FilePath'
chartPath: 'Helm/aks/iaks'
releaseName: '$(releaseName)'
enableTls: true
caCert: 'ca.cert.pem'
certificate: 'helm.cert.pem'
privatekey: 'helm.key.pem'
Listing 8-43ADO Pipeline definition
流水线从构建库的安全文件部分提取 TLS 文件,在代理机器上安装 Helm,然后使用路径`Helm/aks/iaks`中的图表在命名的 AKS 集群上运行`helm install`。
## 摘要
Helm 是一个帮助管理 Kubernetes 上的应用的工具。通过提供图表,Helm 提高了应用的可重用性,并允许通过明确定义的配置值为不同的环境定制应用。Helm 基于 CLI,可以轻松融入现有的自动化流水线和源代码控制。本章是对头盔的介绍,也是在 AKS 上开始使用头盔的指南。
在本章中,您了解了什么是 Helm,以及它如何提供优于 Kubernetes 上的`kubectl`和传统应用部署的优势。我们回顾了准备 AKS 集群以使用 Helm 进行应用管理的过程。然后,我们讨论了 Helm 图的结构以及一个正常工作的 Helm 图包含的内容。借助功能图,您学习了在 Kubernetes 集群上部署和维护 Helm 版本的过程。最后,我们简要回顾了 Helm 如何融入自动化和 CI/CD 的世界。
# 九、使用 Azure Kubernetes 服务的 CI/CD
软件开发已经稳步地向持续集成和持续交付的模型发展。这一过程中的一个关键推动因素是云原生应用的引入。云原生计算基金会将云原生定义为
> *一个开源软件栈,将应用部署为微服务,将每个部分打包到自己的容器中,并动态编排这些容器以优化资源利用率。*
希望其中一些术语对你来说已经开始有点熟悉了。应用的每个部分都打包成一个容器,很可能使用 Docker 映像。微服务由 orchestrator(如 Kubernetes)部署和维护。正如我们将在本章中看到的,如果软件使用容器打包,并以一致和可重复的方式部署,那么持续集成和交付软件的过程将会更加高效。Kubernetes 与 CI/CD 流水线工具(如 Azure DevOps 流水线)相结合,使开发人员能够更快地迭代并创建更可靠的应用。
在这一章中,我们将打破神秘的 CI/CD 缩写,剖析 CI 和 CD 的组成部分。您将看到持续集成软件意味着什么,以及如何使用构建流水线来实现这一点。然后,我们将看看连续交付和部署,以及如何使用发布流水线来完成每一项。最后,我们将回顾一些在 Azure Kubernetes 服务中使用 CI/CD 的最佳实践。
我们将使用前面章节中的 IAKS 投票应用来帮助您将集成、交付和部署的抽象概念应用到现实场景中。投票应用是基于容器的应用,由运行 node.js 的 web 前端和运行 Redis 的存储后端组成,如图 9-1 所示。
![img/484429_1_En_9_Fig1_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig1_HTML.jpg)
图 9-1
投票应用
该项目有用于部署到 Kubernetes 的清单文件,这些文件已经打包在一个 Helm 图表中。我们将遵循更新应用的流程,并将更新部署到开发环境,然后部署到生产环境。
## CI/CD 概述
你可能以前见过缩写词 CI/CD,可能想知道它是什么意思。这是一个看起来很奇怪的缩写,营销人员喜欢把它随意地洒在产品上,就好像它是某种神奇的咒语一样。但是 CI/CD 实际上代表了某些东西,或者更具体地说,它代表了两种东西。CI 代表持续集成,这是开发人员编写代码时,他们应该一天几次将代码签入共享主线的想法。一会儿我们会详细阐述这个想法。
CD 代表连续交付或连续部署。主要思想是软件的最新版本应该是可用的,并且随时可以部署到生产中。如果构建已经准备好了,但是没有在生产中运行,那么我们可以说它已经交付了。如果有一个自动化的过程将交付的构建转移到生产中,那么我们可以说它已经被部署了。这两个选项都方便地缩写为 CD,所以常见的缩写 CI/CD 在这两种情况下都适用。通过上下文可以推断出使用的是哪个“D”——部署还是交付。
## 连续累计
持续集成(CI)是一种软件开发实践,它有一些关键原则,如图 9-2 所示。应该有一个共同的共享代码库,开发人员可以从这里开始工作。开发人员应该检查出最新版本的代码,进行修改,然后将更新后的代码合并回主线。在签入之前,开发人员将获得主线的最新版本,并将任何更改集成到他们的本地版本中。通过经常向主线提交,开发人员永远不会离代码的主线版本太远,因此集成过程会更简单,不太可能需要重构。集成本地代码副本和主线副本的持续过程被称为持续集成。
![img/484429_1_En_9_Fig2_HTML.png](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig2_HTML.png)
图 9-2
持续集成过程
虽然 CI 在理论上是一个好概念,但是直到支持工具集的出现,这个概念才变成现实。支持该过程的主要组件是源代码控制管理(SCM)软件、构建服务器和自动化流水线。对于我们的 IAKS 投票应用示例,我们将使用 Azure DevOps 来提供这些 CI 组件。Azure Repos 将提供基于 git 的 SCM。Azure Pipelines 将提供自动化和构建服务器。Azure Container Registry 将成为存储完整构建工件的目标。
### 共享存储库
当开发人员在代码上进行协作时,通常会有几份代码副本。每个开发人员在他们的工作站上都有一个本地副本,他们将使用它来开发新的特性或功能。还有一个共享的代码库,通常在一个 SCM 服务中,开发者将提交他们的变更并从中获取最新版本的代码。今天最常用的配置管理是 Git,尽管还有其他的如 Subversion、CVS 和 TFS。
### 注意
对软件开发的 Git 和版本控制的全面讨论超出了本章的范围。我们将假设您对源代码控制和分支的概念有些熟悉。如果这对你来说完全陌生,那么我们推荐你查看一下 GitHub 上的 hello-world 活动( [`https://guides.github.com/activities/hello-world/`](https://guides.github.com/activities/hello-world/) )作为入门。
IAKS 投票应用使用 Azure Repos 来托管其代码的共享副本,如图 9-3 所示。用于管理代码的源代码控制机制是 Git。应用有一个用于生产用途的*主*分支和一个用于开发新特性的*特性*分支。一旦一个新的特性被测试和批准,这个分支将被合并到*主*中。
![img/484429_1_En_9_Fig3_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig3_HTML.jpg)
图 9-3
投票应用 git 存储库
### 构建流水线
构建流水线支持将提交的代码与更大的代码库集成。构建流水线是持续集成的一部分,发生在开发人员执行到主线的推送之后。有许多不同的产品会为您运行构建流水线。虽然不同产品的术语可能略有不同,但核心概念是一致的。
生成流水线由生成代理以串行或并行方式执行的一系列步骤组成。构建流水线的输出是一组表示功能应用的工件。发布流水线应该能够获取这些工件并将应用部署到目标环境中。
构建代理通常是运行代理软件并监听新请求的虚拟机。当构建流水线准备好执行某个步骤中的某个任务时,它将查找满足任务要求的可用构建代理,并让该构建代理执行该任务。无论任务成功与否,任务的结果都将报告给构建流水线。此时,流水线可能继续运行,也可能失败,具体取决于任务设置。
IAKS 投票应用将使用 Azure 构建流水线,如图 9-4 所示,作为其 CI 流程的一部分。Azure 构建流水线使用`yaml`来表达它们的配置。流水线定义可以与应用的其余部分一起存在于源代码控制中,确保对流水线的更改与其余代码一起被跟踪和版本化。
![img/484429_1_En_9_Fig4_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig4_HTML.jpg)
图 9-4
持续集成构建流水线
#### 扳机
流水线中的触发器定义了流水线执行的条件。触发器的作用域通常是特定的分支、标记或特性,因此流水线中的步骤只有在作用域内的内容被提交时才会执行。对于大型代码库,确定触发器的范围对于确保只有已更改的组件才能在构建过程中运行非常重要。
IAKS 投票应用使用名为 *features* 的代码分支为应用开发新功能。该应用的当前版本仅支持两个投票选项。有一个功能正在开发中,以增加第三个投票选项。添加该特性的代码使用分支*特性/vote3/0.5* 。清单 9-1 显示了包含触发条件的流水线文件中的代码。
trigger:
branches:
include:
- master
- feature/*
Listing 9-1Trigger conditions
只有向*主*或*特征*下的分支提交,流水线才会启动。
#### 变量
构建流水线不会将每个任务使用的所有值硬编码到文件中。将有动态属性、秘密和计算值用作流水线的一部分。例如,流水线可能需要数据库密码或 API 密钥。该值不应以纯文本形式存储在流水线定义文件中;相反,它可以存储为在构建时注入的秘密。构建号、构建分支和构建日期等属性也是动态的,可以在命名工件时使用。清单 9-2 显示了 IAKS 投票应用构建流水线的变量定义。
variables:
versionNumber: $[format('{0}.{1}', variables['Build.BuildNumber], variables['Build.BuildId'])]
repositoryName: 'iaks'
Listing 9-2Build pipeline variables
虽然这些值是在流水线文件中定义的,但也可以在运行时覆盖这些值。
#### 步伐
构建流水线由流水线进行过程中要采取的步骤组成。一组通用步骤如图 9-5 所示。
![img/484429_1_En_9_Fig5_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig5_HTML.jpg)
图 9-5
持续集成流水线
用于执行每个步骤的构建代理可以在每个步骤中定义,也可以在流水线的开始处定义。更复杂的步骤可能需要具有特定操作系统、专门应用或地理位置的构建代理。在 IAKS 投票应用中,清单 9-3 中的构建代理被定义为一个托管的 Ubuntu 代理,带有最新版本的操作系统。
pool:
vmImage: 'ubuntu-latest'
Listing 9-3Build pipeline agent definition
Azure DevOps 提供按需分配的托管 Windows 和 Linux 代理。也可以在 Azure 或其他地方建立专用的构建代理池。
代码将被测试、打包,并作为工件的集合放置在指定的位置。发布流水线将使用工件来部署应用。
IAKS 投票应用首先构建前端 web 应用容器映像,如清单 9-4 所示。
- task: Docker@2
inputs:
containerRegistry: 'iaks'
repository: 'azure-voting-app'
command: 'buildAndPush'
tags: '$(versionNumber)'
Dockerfile: '**/CICD/azure-vote/Dockerfile'
Listing 9-4Build pipeline docker task
该任务在托管代理上构建映像,然后使用我们之前定义为标签的`versionNumber`变量标记并将映像推送到 Azure 容器注册表(ACR ),以区分多个构建。
清单 9-5 中显示的下一步是获取用于部署应用的 Helm 图表,并将其打包到 Helm 归档文件中。打包过程还将使用提交的版本和应用版本号更新 Chart.yaml 值。
- task: HelmInstaller@1
inputs:
helmVersionToInstall: 'latest' - task: HelmDeploy@0
inputs:
command: 'package'
chartPath: '**/Helm/aks/iaks'
chartVersion: '$(versionNumber)'
arguments: '--app-version $(versionNumber)'
Listing 9-5Build pipeline Helm install
默认情况下,构建代理没有安装 Helm,因此第一个任务安装最新版本的 Helm,第二个任务使用图表版本和应用版本的`versionNumber`变量在本地创建 Helm 包。
我们将打包的 Helm chart 存储在与 web 前端容器映像相同的 ACR 中。Azure CLI 命令用于推送包,因为没有将 Helm 包推送到 ACR 的内置任务,如清单 9-6 所示。
- task: AzureCLI@1
inputs:
azureSubscription: $(AzureSubscriptionId)
scriptLocation: 'inlineScript'
inlineScript: 'az acr helm push \((System.ArtifactsDirectory)/\)(repositoryName)-$(versionNumber).tgz --name $(AzureContainerRegistry);'
Listing 9-6Build pipeline ACR task
清单 9-7 中显示的最后两个任务将这个构建的版本号放到一个文本文件中,并将该文本文件作为工件发布。版本号在变量中定义为 BuildNumber 和 BuildId 的组合。`versionNumber`变量用于标记容器映像和 Helm 图。发布流水线在运行时需要正确的版本号来找到正确的映像和图表。
-
task: Bash@3
inputs:
targetType: 'inline'
script: 'sudo echo $(versionNumber) > $(System.DefaultWorkingDirectory)/versionNumber.txt' -
task: PublishPipelineArtifact@1
inputs:
targetPath: '$(System.DefaultWorkingDirectory)/versionNumber.txt'
artifact: 'versionNumber'
Listing 9-7Build pipeline bash script
#### 通知
当构建流水线完成时,无论成功与否,都应该发出通知。通知有很多选择,最常见的是电子邮件、聊天或 webhook。
Azure DevOps 的通知在流水线之外处理,在项目设置中定义。第三方应用,如 Slack,可以直接订阅某个版本或发布,并向特定频道提供通知。IAKS 投票应用在一个名为 *iaks* 的松弛通道上被监控。当一个构建流水线完成时,图 9-6 中的以下通知出现在通道中。
![img/484429_1_En_9_Fig6_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig6_HTML.jpg)
图 9-6
Azure 流水线通知
#### 史前古器物
一个成功的构建流水线将产生工件,发布流水线可以使用这些工件来交付并可能部署应用。由构建产生的工件应该被一致地用于在较低的环境和生产中发生的任何验收测试。这保证了在产品化或 QA 中部署的任何代码都将与在生产中部署的代码相匹配。强烈反对在构建流水线之外修补工件,就像永远不要这样做一样。
你为什么不应该修补那些艺术品?假设您已经构建了应用的新版本,并将其部署到 QA 和试运行中。在登台环境中有一个小问题,但是您发现您可以通过调整配置文件中的设置来修复它。
您进行了更改,现在测试通过了。因为您在产品化阶段调整了工件,所以正在部署的代码不再匹配源代码控制中的内容。在随后的构建中,您的更改将会丢失,您修复的东西现在又会被破坏。
充其量,你打破了舞台。在最坏的情况下,丢失的变更会进入生产环境,并在那里中断。故事的士气?不要改动文物。更改代码并运行新版本。
IAKS 投票应用创建了三个工件。web 前端容器映像、Helm 图表和`versionNumber`文本文件。容器映像和图表存储在 Azure 容器注册实例中。该文本文件作为构建中的工件发布,这使得它可用于任何发布流水线。当我们进入发布流水线部分时,我们将看到来自构建的工件是如何被发布所吸收和使用的。
## 持续交付/部署
正如本章开头所提到的,CD 可以代表持续交付或部署。主要的区别是自动化过程在什么点停止。在连续交付环境中,CD 流水线的末端是生产就绪版本。有一个手动步骤可以将发布正式部署到生产中。连续部署环境会自动完成最后一步。
### 注意
在本节中,我们将主要关注如何建立一个连续的交付流水线。适用时,将明确注明持续部署。
### 释放流水线
构建流水线的最终结果是组成应用的一组工件。这些工件应该处于可部署的状态。发布流水线的工作是获取这些工件,将应用部署到一个或多个环境中,并运行测试来验证应用的功能。图 9-7 显示了一个常见的释放流水线示例。
![img/484429_1_En_9_Fig7_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig7_HTML.jpg)
图 9-7
连续输送流水线
流水线将提取由特定构建创建的工件。然后,它将工件作为应用部署到开发环境中,并运行系统测试。假设这些系统测试通过,流水线将创建一个 pull 请求,将 feature 分支合并到 master 分支中。然后,流水线将把相同的工件部署到一个进行验收测试的阶段环境中。如果验收测试是成功的,那么工件可以被标记为生产就绪,或者被转移到一个只生产的存储库中。工件向生产存储库的移动可以作为一个触发器,启动将这些工件部署到生产的流水线中的另一个阶段。
IAKS 投票应用使用来自 Azure Pipelines 的两个发布流水线来处理连续交付。从*功能*分支构建的代码将触发 helm-dev-release 流水线。该流水线将从特性构建中提取工件,并将它们部署到 AKS 集群上的*开发*名称空间。除了使用单一的开发名称空间,还可以在 AKS 集群上启用 Dev Spaces 特性。Dev Spaces 创建了一个可由多个开发人员共享的专用开发环境,能够在更大的开发环境中创建每个用户的空间,以实时测试新特性。
当代码通过 pull 请求合并到 *master* 分支时,会触发 helm-qa-release 流水线。该流水线将从上一次成功的构建中提取工件,并将它们部署到 AKS 集群上的 *qa* 名称空间。一旦执行了验收测试,将调用第二个阶段,从构建中提取工件,并将它们复制到 ACR 上的生产存储库中。还有第三个手动阶段,将生产标记的工件部署到生产 AKS 集群。
Azure 发布流水线使用图形用户界面来表达,而不是通过`yaml`文件。这很可能很快会改变,使构建和发布流水线之间的接口一致。可以使用`JSON`文件导出或导入发布流水线。对于本节中的示例,屏幕截图将用于显示发布流水线配置的相关部分。
#### 扳机
CD 流水线的常见触发因素是 CI 流水线的成功完成。也可能有这样的情况,触发器是基于时间的,按每天的时间表触发,或者基于来自另一个分支的拉请求。
IAKS 投票应用由来自*功能*分支的代码的成功构建或来自*主*分支的拉请求触发。Helm 开发释放流水线上特征分支触发器的配置如图 9-8 所示。
![img/484429_1_En_9_Fig8_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig8_HTML.jpg)
图 9-8
连续部署触发器
每当来自*特性*路径上的分支的新构建可用时,该流水线将执行。图 9-9 中显示的 helm-qa-release 的配置是相同的,除了构建分支被设置为*主*并且增加了一个拉取请求触发器。
![img/484429_1_En_9_Fig9_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig9_HTML.jpg)
图 9-9
Azure Pipelines QA 版本
#### 阶段
CD 流水线中各阶段的术语取决于软件,但一般来说,CD 流水线中会有多个阶段。每个阶段可以由一个或多个作业组成,每个作业由一个或多个任务组成。阶段和作业可以是连续的,也可以是并行运行的。作业中的任务通常是连续运行的。
图 9-10 中的 Helm-dev-release 管线由单级组成,只有一个作业。
![img/484429_1_En_9_Fig10_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig10_HTML.jpg)
图 9-10
Azure 流水线开发版本
该阶段的工件来源于构建过程。工件可能有多个来源。在有几个微服务的大型应用中,工件可能来源于每个微服务流水线的成功构建。
图 9-11 中的 Helm-qa-release 由三个阶段组成,每个阶段有一项工作。
![img/484429_1_En_9_Fig11_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig11_HTML.jpg)
图 9-11
Azure Pipelines 临时发布
所有阶段的作业都在发布代理上运行,就像构建任务在构建代理上执行一样。开发发布工作如图 9-12 所示,以供参考。
![img/484429_1_En_9_Fig12_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig12_HTML.jpg)
图 9-12
Azure 流水线代理配置
在图 9-12 中,您可以看到代理首先下载包含 versionNumber.txt 文件的流水线工件。下面的任务是一个 bash 脚本,它从文本文件中获取版本号,并用该版本号设置一个发布流水线变量。然后,代理安装 Helm 并使用 Azure CLI 添加 ACR 存储库,用于部署的 Helm 图表驻留在该存储库中。最后,在图 9-13 中,Helm 使用 Helm 图表和容器映像在*开发*名称空间中的 AKS 集群上运行升级,这些图表和容器映像是构建流水线中工件的一部分。
![img/484429_1_En_9_Fig13a_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig13a_HTML.jpg) ![img/484429_1_En_9_Fig13b_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig13b_HTML.jpg)
图 9-13
Azure 流水线掌 Helm 部署
当部署完成后,AKS 集群中的*开发*名称空间将运行 IAKS 投票应用的新部署,如清单 9-8 所示。
helm ls --tls --namespace development
NAME STATUS CHART APP VERSION
iaks-45 DEPLOYED iaks-20190725.4.45 20190725.4.45
iaks-46 DEPLOYED iaks-20190725.4.46 20190725.4.46
Listing 9-8Helm deployment listing
每个版本的命名都包含了`BuildId`属性,所以每个成功的构建都将被创建为它自己在 AKS 集群上的部署。helm-qa-release 使用相同的任务将应用的副本部署到 *qa* 名称空间,但是它不使用`BuildId`属性来命名 helm release。因此,当 helm-qa-release 流水线运行时,它会就地升级任何现有的应用。
在 helm-qa-release 中的部署任务结束时,图 9-14 显示有一个批准条件。QA 部门的某个人需要审查部署,并验证它已经通过了所有的验收标准。
![img/484429_1_En_9_Fig14_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig14_HTML.jpg)
图 9-14
Azure 流水线后期部署
通过批准试运行-发布阶段,执行流水线中的下一个标记工件阶段,如图 9-15 所示,该阶段涉及将构建工件移动到生产存储库。在 Azure Container Registry 中,有一个单独的注册表实例叫做 *acriaksprod* 。标记工件阶段的目标是将存储在 *acriaks* 中的工件转移到 *acriaksprod* 中。
![img/484429_1_En_9_Fig15_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig15_HTML.jpg)
图 9-15
Azure 流水线标记工件
部署流程下载`versionNumber.txt`工件并将其作为变量导入。然后,它安装 Helm 和 Docker 客户端。第一个 Azure CLI 任务将 *acriaks* ACR 添加为 Helm 存储库。
az acr helm repo add -n $(acrName)
然后,Helm 任务从 *acriaks* 库中获取 *iaks* 图表,并将其保存在本地。
helm fetch $(acrName)/iaks
在清单 9-9 中显示的最后一个任务中,Azure CLI 首先将 Helm 图推送到 *acriaksprod* 存储库。然后,它同时登录到 *acriaks* 和 *acriaksprod* 。使用 docker CLI,它从 *acriaks* 中提取当前 web 前端映像,为 *acriaksprod、*重新标记它,并将映像推送到 *acriaksprod* 。
az acr helm push iaks-$(versionNumber).tgz --name $(acrName)prod
az acr login -n $(acrName)prod
az acr login -n $(acrName)
docker pull \((imagePath):\)(versionNumber)
docker tag \((imagePath):\)(versionNumber) \((prodImagePath):\)(versionNumber)
docker push \((prodImagePath):\)(versionNumber)
Listing 9-9Azure CLI tasks
掌 Helm 图和 web 前端映像现在都存储在生产存储库中,并准备好部署到生产中。生产环境运行在单独的 AKS 集群上。我们可以使用`ImagePolicyWebhook`配置准入策略,只允许将存储在 *acriaksprod* 注册表中的映像部署到生产集群。
在 helm-qa-release 中有一个单独的阶段,如图 9-16 所示,可以手动运行以部署到生产中。
![img/484429_1_En_9_Fig16_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig16_HTML.jpg)
图 9-16
Azure Pipelines 产品发布
生产-发布阶段中的任务反映了阶段-发布阶段中的任务,但是如图 9-17 所示,一些值已经被更改,以使用正确的 ACR 实例 *acriaksprod* ,并部署到为生产使用保留的单独的 AKS 集群。
![img/484429_1_En_9_Fig17_HTML.jpg](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig17_HTML.jpg)
图 9-17
Azure 流水线生产掌 Helm 任务
尽管生产-发布阶段目前被设置为手动触发——使其成为一个连续的交付流水线——但它可以更新为在标记工件阶段完成并由一组选定的人员批准后触发。
## 测试
正确的测试是整个 CI/CD 流程不可或缺的一部分。测试有不同的阶段,每个测试都建立在最后一个之上。最终,测试的目标是产生满足技术和商业需求的可靠软件。在代码被推送到共享存储库之前,一部分测试将在开发人员的工作站上进行。一旦代码被推送到共享存储库,CI 流水线将开始执行。CI 流水线的步骤将包括自动化测试,有时还包括手动测试,目标是生产稳定的软件,可以在 QA 或试运行环境中部署和测试。CI/CD 环境中的最后一组测试将在 CD 流水线中执行,希望最终能够发布一个可以在生产中部署的可接受的版本。
根据部署模型的不同,测试不一定在部署到生产环境时就结束了。代码可能会逐渐推广到一部分用户或某些地理位置。部署期间收集的遥测数据可用于进一步验证软件是否按预期工作。
在接下来的小节中,我们将简要地看一下一些更常见的测试阶段,以及它们在 CI/CD 过程的大环境中所处的位置。
### 单元测试
当开发一个新的特性或功能时,它必须满足一些需求。对于一组给定的输入,它应该产生一定的输出。例如,假设您正在开发一个将两个整数相加的函数。单元测试将验证给定两个整数-1 和 2-该函数产生预期的 3。单元测试将有几种情况要测试,包括无效输入,如浮点数或文本而不是整数。我们可能知道花生酱和巧克力等于棒极了,但是我们的加法函数可能会抛出一个错误。
单元测试将在开发人员的本地工作站上进行,或者在 CI 流水线的早期阶段进行。
### 集成测试
在一个特性或功能通过自身验证后,它需要与应用的其他部分进行交互测试。在我们的例子中,很有可能应用的某些部分已经在使用一个函数将整数相加。当您用新功能替换该功能时,您必须测试应用的这些部分,以确保它们仍然正常工作。换句话说,您正在测试代码与它所交互的组件的集成。
集成测试将作为 CI 流水线中的一个阶段进行,然后发布构建以在下一个测试阶段进行部署。
### 系统试验
云原生应用由微服务组成,每个微服务向应用的其他组件或外部源提供服务。虽然不是所有的组件都将直接与被更新的代码部分交互,但是仍然可能存在不可预见的附带影响。系统测试是在整个应用上执行的,而不仅仅是在那些直接与更新交互的组件上。在我们的例子中,这将是一个标准的测试套件,适用于整个应用,而不仅仅是使用您的新的和完全令人敬畏的加法函数的部分。
系统测试将在构建版本之后进行,通常是在开发或 QA 环境中测试版本的 CD 流水线期间。
### 验收测试
系统测试从技术角度确定系统是否按预期工作,但是还有其他的验证标准。安全、法规遵从性和 QA 团队可能希望运行他们的自动化或手动测试套件来验证应用是否满足他们的业务需求。有时一组用户也会被包括在测试中,以确保用户群体对应用的功能感到满意。
验收测试将在 CI 流水线完成之后、应用部署到生产环境之前进行。在一个 CD 流水线中可能会有几轮由不同团队进行的验收测试,最终会产生一个可以投入生产的版本。
### 开发空间
在 AKS 中,有一个名为 Dev Spaces 的功能目前正在预览中。Dev Spaces 背后的意图是使个人开发者的开发和测试过程更简单。实际上,在 AKS 集群中创建了一个父开发空间,为团队中的每个开发人员创建了一个或多个子空间,如图 9-18 所示。在父空间中,部署了应用的完整版本。当开发人员对他们的代码进行更新时,产生的构建被部署在他们唯一的空间中,但是它可以与运行应用其余部分的父空间进行交互。
![img/484429_1_En_9_Fig18_HTML.png](https://gitee.com/OpenDocCN/vkdoc-devops-zh/raw/master/docs/intro-azure-k8s-svc/img/484429_1_En_9_Fig18_HTML.png)
图 9-18
开发空间布局
例如,让我们考虑一个包含时间跟踪服务的微服务应用。您可能正在使用时间跟踪服务,该服务与组成应用的许多其他服务进行交互。不是试图在您的工作站上运行整个应用,而是在称为*开发*的开发空间中的 AK 上运行应用的实例。当您提交新版本的时间跟踪服务时,Dev Spaces 可以在您的个人空间(一个名为 *Development/Dev1* 的子空间)中部署生成的 pod。出于测试目的,您现在可以在*开发*中使用应用,但是让您的应用端点在*开发/Dev1* 中使用更新的时间跟踪服务。一旦您成功地执行了您的单元和集成测试,您可以将您的代码合并到开发分支中,并且在*开发*空间中的应用将被更新。
Dev Spaces 确实需要准备代码来使用它,创建一个 Dev Spaces 配置文件,并使用一些客户端工具来与之交互。主要的好处是,开发人员不必尝试维护应用的本地副本来进行测试,团队中的每个人都使用已经在 Kubernetes 中运行的公共环境来执行测试和调试。
## AK 的 CI/CD 最佳实践
谈到 CI/CD,有许多最佳实践,我们不会在这里试图总结它们。相反,我们希望将 CI/CD 应用于 Azure Kubernetes 服务。最佳实践可以分为两个不同的领域,集群操作员和应用开发人员。
### 聚类运算符
集群操作员负责管理和维护 AKS 集群。他们负责配置集群的安全性、更新 Kubernetes 的版本、配置伸缩和节点池等等。如果您经常部署和更改 AKS 集群,您可能属于这一类。集群操作者主要关心 CI/CD 的持续交付部分,尽管他们可能会参与帮助开发人员开发空间或为集成测试划分许可的名称空间。
#### 独立的环境
当涉及到交付和部署时,一个版本会经历几个环境:开发、QA、试运行、生产,等等。这些环境需要某种程度的分离,有两种主要方法可以实现这一点,名称空间和集群。
Kubernetes 中的名称空间是分离工作负载的逻辑结构。命名空间可以在 RBAC 规则中使用,限制帐户可以部署到哪些命名空间。命名空间也有自己的 DNS 空间用于名称解析,例如,开发命名空间中的服务可能有地址 app . development . SVC . cluster . local。命名空间可能有分配给它们的资源配额,允许您限制命名空间在群集内可以使用的资源量。
对于不需要彼此硬分离的环境,名称空间具有逻辑意义。需要特别注意防火墙规则和限制,因为名称空间不提供相互之间的网络分离或分段。一个常见的最佳实践是使用名称空间来分隔多个开发环境,以及其他非生产环境。
AKS 中的集群在环境之间提供了更强的隔离。从 Kubernetes 管理的角度来看,每个集群都是完全独立的。从网络的角度来看,创建一个单独的集群提供了一个额外的分段级别,这对于某些环境(如生产环境)可能是理想的。多个集群增加了管理负担,因为现在集群操作员负责管理和维护它们。一个常见的最佳实践是为生产环境或其他可能需要更高级别的隔离的环境使用单独的集群。
还有第三种可能的选择,那就是在 AKS 中使用节点池。AKS 正在预览节点池,但在不久的将来应该会正式推出。一个群集可以有多个节点池,每个节点池由相同大小和类型的节点组成。通过使用节点污染和选择器,可以将环境分成不同的节点池,这将增加隔离,而不需要管理另一个 AKS 集群。
#### 限制访问
有了合适的发布渠道,开发人员不应该直接部署到 AKS。他们应该遵循提交代码的过程,让 CI 和 CD 流水线完成剩下的工作。除了 Dev Spaces,开发人员不应该有权限直接部署到 AKS 中的任何环境。
构建和发布流水线可以与 Azure 中的服务主体相关联,这些服务主体可以被授予部署到 AKS 的必要权限。每个环境都应该有自己的服务主体,对编辑流水线的访问也应该受到限制。
限制开发人员的访问,以及您自己的访问,会迫使每个人都遵循 CI/CD 流程,并阻止他们在流程之外进行可能在未来的部署中被遗忘或忽略的更改。
#### 准入控制
集群上的准入控制有助于确定是否接受部署,或者在接受之前是否需要对部署进行任何更改。这可能包括要求特定的标签、资源限制或映像注册。为了防止发布流水线中可能的篡改,最佳实践是创建阻止某些部署成功的准入策略。根据您在 AKS 集群上运行的 Kubernetes 版本,AKS 启用了几个准入控制插件。
#### 用于部署的 Azure 监视器
Azure Monitor 是微软 Azure 中多个监控服务的组合。运行有效的 CI/CD 操作的很大一部分是收集反馈。集群操作员主要关心部署或集群维护后应用的运行状况。Azure Monitor 可以配置为从 AK 收集信息,供操作员在警报或趋势分析中使用。
### 应用开发人员
集群操作员关心其权限内 AKS 集群的正常运行和维护。应用开发人员关注他们的应用的健康和性能。如果您正在编写将在 AKS 集群上运行的代码,您可能属于这一类。应用开发人员关心 CI/CD 的持续集成和持续交付组件。
#### 调试立方结构
根据应用运行的环境,它们的功能可能会有所不同。为此,在最接近生产条件的环境中测试和调试应用是有意义的。AKS 提供了在 Kubernetes 上直接调试的能力,或者通过整个团队的专用开发环境,或者通过 Dev Spaces。特别是使用 Dev Spaces 为整个团队提供了一个公共的基线环境,同时仍然允许对应用的特定组件进行单独的开发和调试。
#### 外部存储凭据
凭证和其他机密信息不应该放入代码、部署文件或 CI/CD 流水线中。它们应该存储在一个安全的保险库中,在应用运行时可以通过适当的权限和安全控制进行访问。
AKS 和 Azure DevOps 能够利用 Azure Key Vault。AKS 和 Azure DevOps 都使用 Azure Active Directory 对 Key Vault 进行身份验证,并访问存储在那里的机密、证书和密钥。AKS 可以使用其节点的托管安全身份和 pod 级 Azure AD 身份验证来访问密钥库。
应用开发人员应该利用 Azure Key Vault 集成将任何凭据、机密和证书移出他们的代码。
#### Azure 发展监控
Azure Monitor 是微软 Azure 中多个监控服务的组合,包括应用洞察和日志分析。日志、跟踪和调试信息都可以发送到 Azure Monitor 进行警告和分析。虽然集群运营商关心他们的 AKS 集群的健康状况,但开发人员更关注他们的应用的健康状况,尤其是在部署新版本的应用或流量突然激增时。CI/CD 流水线还可以在每个阶段执行时向 Azure Monitor 发送信息,使数据可用于警报和分析。
应用开发人员应该在他们的代码和流水线中添加挂钩,以支持额外的 Azure Monitor 集成。
## 摘要
在更大的 DevOps 世界中,持续集成和持续交付是巨大的主题。虽然我们刚刚触及了 CI/CD 背后的一些核心概念,但是我们希望您能够看到 AKS 是如何与软件的自动化构建和发布联系在一起的。一般来说,Kubernetes,特别是 AKS,为开发和部署云原生应用提供了一致且稳定的环境。与 CI/CD 原则协同工作,可以快速迭代并为最终用户生成稳定的应用。
在本章中,您学习了什么是 CI/CD,以及源代码控制、应用构建和发布流水线背后的一些基础知识。我们回顾了 Azure DevOps 中的构建流水线,并看到了代码提交如何产生可交付的可用工件。然后,我们看了一个发布流水线,以及如何使用相同的工件在多个环境中部署应用。最后,我们回顾了将 AK 与 CI/CD 结合使用的一些最佳实践。