08-27-周三_17-09-29
829
Ansible.html
Normal file
8
Docker/Docker.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Docker是什么?
|
||||
|
||||
Docker 是一个用于开发、发布和运行应用程序的开放平台。Docker 可让将应用程序与基础架构分离,以便快速交付软件。借助 Docker,可以像管理应用程序一样管理基础架构。通过利用 Docker 的发布、测试和部署代码方法,可以显著减少编写代码和在生产中运行代码之间的延迟。
|
||||
|
||||
|
||||
[Docker官方文档](https://docs.docker.com/)
|
||||
|
||||
[Docker项目地址](https://github.com/docker)
|
69
Docker/Docker介绍.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Docker平台
|
||||
|
||||
Docker 提供了在松散隔离的环境中打包和运行应用程序的功能,该环境称为容器。隔离和安全性可以在给定主机上同时运行多个容器。容器是轻量级的,包含运行应用程序所需的一切,因此无需依赖主机上安装的内容。可以在工作时共享容器,并确保与共享的每个人都能获得以相同方式工作的相同容器。
|
||||
|
||||
Docker 提供工具和平台来管理容器的生命周期:
|
||||
- 使用容器开发应用程序及其支持组件。
|
||||
- 容器成为分发和测试应用程序的单元。
|
||||
- 应用程序作为容器或编排服务部署到生产环境(本地数据中心、云提供商等等)。
|
||||
|
||||
|
||||
# Docker使用场景
|
||||
|
||||
## 快速、一致地交付应用程序
|
||||
|
||||
Docker 允许开发人员使用提供应用程序和服务的本地容器在标准化环境中工作,从而简化了开发生命周期。容器非常适合持续集成和持续交付 (CI/CD) 工作流程。
|
||||
|
||||
**示例场景:**
|
||||
- 开发人员本地编写代码并使用 Docker 容器与同事共享他们的工作。
|
||||
- 使用 Docker 将应用程序推送到测试环境并运行自动和手动测试。
|
||||
- 发现错误时,可以在开发环境中修复它们,并将其重新部署到测试环境中进行测试验证。
|
||||
- 测试验证完成后,将修复后代码构建成镜像并更新至生产环境并部署容器运行。
|
||||
|
||||
## 响应式部署和扩展
|
||||
|
||||
Docker 基于容器的平台是高度可移植的。Docker 容器可以在开发人员的本地笔记本电脑、数据中心的物理机或虚拟机、云提供商或混合环境中运行。
|
||||
|
||||
Docker 的可移植性和轻量级特性还使其能够轻松地动态管理,根据业务需求近乎实时地扩大或拆除应用程序和服务。
|
||||
|
||||
## 在相同硬件上运行更多应用
|
||||
|
||||
Docker 轻量且快速。它为基于虚拟机的服务程序管理提供了一种可行且经济高效的替代方案,因此可以使用更多的服务器容量来实现业务目标。Docker 非常适合高密度环境以及需要使用更少资源完成更多任务的中小型部署。
|
||||
|
||||
|
||||
# Docker架构
|
||||
|
||||
Docker 使用客户端-服务器架构。Docker 客户端与 Docker 守护程序通信,后者负责构建、运行和分发 Docker 容器的繁重工作。Docker 客户端和守护程序可以在同一系统上运行,或者可以将 Docker 客户端连接到远程 Docker 守护程序。Docker 客户端和守护程序使用 REST API、通过 UNIX 套接字或网络接口进行通信。另一个 Docker 客户端是 Docker Compose,可以管理由一组容器组成的应用程序。
|
||||
|
||||

|
||||
|
||||
## Docker Host
|
||||
|
||||
Docker Host是一款易于安装的应用程序,适用于 Mac、Windows 或 Linux 环境,可让构建和共享容器化应用程序和微服务。Docker Host 包括 Docker 守护程序 ( `dockerd` )、Docker 客户端 ( docker )、Docker Compose、Docker Content Trust、Kubernetes 和 Credential Helper。
|
||||
|
||||
## Docker Daemon
|
||||
|
||||
Docker 守护程序 ( `dockerd` ) 监听 Docker API 请求并管理 Docker 对象(例如images、containers、networks和volumes)。守护程序还可以与其他守护程序通信以管理 Docker 服务。
|
||||
|
||||
## Docker Client
|
||||
|
||||
Docker 客户端 ( `docker` ) 是许多 Docker 用户与 Docker 交互的主要方式。当使用诸如 `docker run` 类的命令时,客户端会将这些命令发送到 `dockerd` ,后者会执行这些命令。`docker` 命令使用 Docker API。Docker 客户端可以与多个守护程序进行通信。
|
||||
|
||||
## Docker Registry
|
||||
|
||||
Docker 镜像仓库是存储 Docker 镜像。Docker Hub 是个公共镜像仓库,Docker 默认会在 Docker Hub 上查找镜像。也可以运行自己的私有镜像仓库。
|
||||
|
||||
当使用 `docker pull` 或 `docker run` 命令时,Docker 会从配置的镜像仓库地址中拉取所需的镜像。当使用 `docker push` 命令时,Docker 会将镜像推送到配置的镜像仓库。
|
||||
|
||||
## Docker Objects
|
||||
|
||||
**Images**
|
||||
镜像是创建 Docker 容器的模版。通常可以基于其他镜像进行二次构建。例如,已经有 `ubuntu` 镜像,但我们还要安装 Apache Web服务 + 应用 + 自定义配置。
|
||||
|
||||
基于别人发布在镜像仓库中的镜像,编写 Dockerfile 构建自己的镜像。Dockerfile 中的每条指令都会在镜像中创建一个层。更改 Dockerfile 并重建镜像时,只会重建已更改的层。这正是与虚拟化技术相比,镜像如此轻量、小巧和快速的原因之一。
|
||||
|
||||
**Containers**
|
||||
容器是镜像的运行实例。可以使用 Docker API 或 CLI 创建、启动、停止、移动或删除容器。可以将容器连接到一个或多个网络、附加存储,甚至根据其当前状态创建新镜像。
|
||||
|
||||
容器由其镜像和创建或启动容器时提供的任何配置选项定义。当容器被删除时,未持久化存储的更改都会消失。
|
||||
|
90
Docker/Docker仓库管理.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# 公共仓库
|
||||
|
||||
## 官方Docker仓库
|
||||
|
||||
1. 准备账户: 登陆到[Docker Hub](https://hub.docker.com/)官网创建账号,登陆后点击settings完善信息。
|
||||
2. 填写账户基本信息: 重置密码/生成`accesstoken`
|
||||
3. `docker login docker.io` 输入用户密码即可
|
||||
4. 国内可能因为网络问题,需要代理
|
||||
|
||||
## 阿里云镜像仓库
|
||||
|
||||
1. 准备账户: 登录到[Aliyun Hub](https://cr.console.aliyun.com/)官网创建账号
|
||||
2. 容器镜像服务->实例列表->镜像仓库->创建镜像仓库
|
||||
3. 执行操作指南
|
||||
|
||||
```shell
|
||||
# 1.登录阿里云Docker Registry
|
||||
$ docker login --username=15295733404 registry.cn-hangzhou.aliyuncs.com
|
||||
# 2.从Registry中拉取镜像
|
||||
$ docker pull registry.cn-hangzhou.aliyuncs.com/zhaohao/eagleslab:[镜像版本号]
|
||||
# 3.将镜像推送到Registry
|
||||
$ docker login --username=15295733404 registry.cn-hangzhou.aliyuncs.com
|
||||
$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/zhaohao/eagleslab:[镜像版本号]
|
||||
$ docker push registry.cn-hangzhou.aliyuncs.com/zhaohao/eagleslab:[镜像版本号]
|
||||
# 4.选择合适的镜像仓库地址: 公网访问/VPC网络内访问
|
||||
```
|
||||
|
||||
# 私有仓库
|
||||
|
||||
## docker registry
|
||||
|
||||
Docker Register作为Docker的核心组件之一负责镜像内容的存储与分发,客户端的docker pull以及push命令都将直接与register进行交互,最初版本的registry由python实现的,由于涉及初期在安全性、性能以及API的设计上有着诸多的缺陷,该版本在0.9之后停止了开发,由新的项目distribution(新的docker register被称为Distribution)来重新设计并开发了下一代的registry,新的项目由go语言开发,所有的api底层存储方式,系统架构都进行了全面的重新设计已解决上一代registry的问题。
|
||||
|
||||
官方文档地址:https://docs.docker.com/registry
|
||||
|
||||
官方github地址: https://github.com/docker/distribution
|
||||
|
||||
**部署**
|
||||
```shell
|
||||
# 执行安装脚本
|
||||
[root@master01 scripts]# ./install/install_registry.sh
|
||||
```
|
||||
|
||||
## 企业级方案Harbor
|
||||
|
||||
参考网址:https://goharbor.io/docs/2.3.0/install-config/
|
||||
|
||||
Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,由vmware开源,其通过添加一些企业必须的功能特性,例如安全、标识和管理等,扩展了开源的Docker Distribution。Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等。
|
||||
|
||||
**部署**
|
||||
```bash
|
||||
# 1.准备安装包
|
||||
[root@docker-server1 ~]# wget https://github.com/goharbor/harbor/releases/download/v2.3.1/harbor-offline-installer-v2.3.1.tgz
|
||||
[root@docker-server1 ~]# tar xzvf harbor-offline-installer-v2.3.1.tgz
|
||||
[root@docker-server1 ~]# ln -sv /root/harbor /usr/local/
|
||||
"/usr/local/harbor" -> "/root/harbor"
|
||||
# 2.配置文件
|
||||
[root@docker-server1 harbor]# cp harbor.yml.tmpl harbor.yml
|
||||
[root@docker-server1 harbor]# grep -Ev '#|^$' harbor.yml.tmpl > harbor.yml
|
||||
[root@docker-server1 harbor]# cat harbor.yml
|
||||
# 3.执行安装
|
||||
[root@docker-server1 harbor]# ./prepare
|
||||
[root@docker-server1 harbor]# ./install.sh
|
||||
# 之后的启动关闭可以通过docker-compose管理,自动生成docker-compose.yml文件
|
||||
[root@docker-server1 harbor]# ls
|
||||
common docker-compose.yml harbor.yml install.sh prepare
|
||||
common.sh harbor.v2.3.1.tar.gz harbor.yml.tmpl LICENSE
|
||||
```
|
||||
**web访问**
|
||||
默认用户名和密码在harbor.yml中设置为:harbor_admin_password: Harbor12345
|
||||
|
||||
**推送镜像**
|
||||
参考网站推送教学
|
||||
|
||||
```bash
|
||||
# 登录
|
||||
[root@docker-server2 ~]# grep 'insecure' /etc/docker/daemon.json
|
||||
"insecure-registries":["192.168.175.10"]
|
||||
[root@docker-server2 ~]# systemctl daemon-reload & systemctl restart docker
|
||||
[root@docker-server2 ~]# docker login 192.168.204.135
|
||||
Username: admin
|
||||
Password:
|
||||
...
|
||||
Login Succeeded
|
||||
[root@admin harbor]# docker-compose restart
|
||||
|
||||
# 推送
|
||||
[root@docker-server2 nginx]# docker tag nginx:v1 192.168.175.10/eagles/nginx:v1
|
||||
[root@docker-server2 nginx]# docker push 192.168.175.10/eagles/nginx:v1
|
||||
```
|
90
Docker/Docker存储引擎.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# 存储引擎
|
||||
|
||||
Docker 存储引擎是 Docker 容器管理文件系统的核心组件,负责镜像层与容器层的组织、读写操作及资源隔离。其核心在于通过联合文件系统(UnionFS)和写时复制(Copy-on-Write, CoW)机制实现高效存储管理。
|
||||
|
||||
## 分层存储与联合挂载
|
||||
|
||||
Docker镜像由多个只读层(Layer)叠加而成,容器运行时会在镜像层之上创建可写层。所有层通过 UnionFS 联合挂载到同一视图,上层文件覆盖下层同名文件,但底层数据保持不变。
|
||||
|
||||
UnionFS(联合文件系统)是一种分层、轻量级且高性能的文件系统技术,通过将多个目录(分支)联合挂载到同一目标目录,形成统一的文件系统视图。核心机制如下:
|
||||
- **分层存储**:UnionFS 通过分层结构管理文件,每个层(分支)可以是只读或可写。不同层中相同路径的文件会被上层覆盖,但底层内容保持不变。
|
||||
- **只读层和可写层**:只读层通常为基础镜像或依赖文件,不可修改;可写层:容器运行时新增的层,所有修改均在此层记录。
|
||||
|
||||
## 写时复制(CoW)机制
|
||||
|
||||
当容器需要修改文件时,存储引擎将文件从底层只读层复制到可写层进行修改,而非直接修改原始数据。这种机制减少冗余存储,允许多容器共享同一镜像层,显著降低磁盘占用。
|
||||
|
||||
## 工作原理
|
||||
|
||||
- **联合挂载(Unio Mount)**:将多个物理目录(如目录A和B)挂载到同一虚拟目录(如目录C),合并后的视图包含所有分支目录的内容。若存在同名文件,优先显示上层文件。
|
||||
- **访问优先级**:用户访问文件时,UnionFS按层从上至下搜索,返回第一个匹配的文件。例如,可写层优先级高于只读层。
|
||||
- **数据隔离与共享**:不同容器共享同一基础镜像层,但各自的可写层独立,实现资源复用与运行时隔离。
|
||||
|
||||
# 主流存储引擎
|
||||
|
||||
Docker支持多种存储驱动,不同驱动在性能、稳定性、适用场景上存在差异:
|
||||
|
||||
| 存储驱动 | 特点 | 优势 | 局限性 | 适用场景 |
|
||||
|---------|------|------|--------|----------|
|
||||
| OverlayFS | • Linux内核原生支持(≥3.18)<br>• 使用overlay2驱动<br>• 仅需一个只读层和一个可写层<br>• 结构简单且性能优异 | • 启动速度快<br>• 适合生产环境<br>• 支持高效的文件系统层叠<br>• 节省存储空间 | • 层数限制(通常≤127层)<br>• 频繁小文件写入可能增加I/O开销 | • 通用容器环境<br>• 需要高性能的生产系统<br>• 对存储空间敏感的场景 |
|
||||
| AUFS | • 通过多层联合挂载实现CoW<br>• 稳定性较好<br>• 未集成到内核,需额外安装 | • 内存利用率高<br>• 适合旧版Linux系统 | • 高并发写入性能较差<br>• 逐渐被OverlayFS替代 | • 旧版Linux系统<br>• 对内存资源敏感的环境<br>• 低并发写入场景 |
|
||||
| Device Mapper | • 基于块设备映射<br>• 使用"thin pool"技术<br>• 支持动态扩容 | • 支持精细的存储控制<br>• 适合块级存储需求<br>• 动态扩容能力强 | • 配置复杂<br>• 需预分配存储池<br>• 可能导致空间浪费 | • 数据库容器<br>• 需要精细存储控制的场景<br>• 大规模存储系统 |
|
||||
| Btrfs/ZFS | • 支持高级功能(快照/去重/压缩)<br>• 文件系统级别的功能丰富 | • Btrfs写入密集型场景表现优异<br>• ZFS提供数据完整性校验<br>• 支持高效压缩 | • 对系统内核版本依赖性强<br>• 稳定性与兼容性需验证 | • 需要数据快照功能<br>• 写入密集型应用<br>• 对数据完整性要求高的场景 |
|
||||
|
||||
# Overlay2
|
||||
|
||||
## 工作原理
|
||||
|
||||
Docker 默认存储驱动。通过以下三个主要目录来管理文件系统:
|
||||
- **`LowerDir`**:只读层,包含基础镜像的文件系统。可以有多个只读层,每层都是独立的。
|
||||
- **`UpperDir`**:读写层,用于存储容器运行时的文件系统变更(即 diff 层)。
|
||||
- **`MergedDir`**:联合挂载后的视图,容器看到的完整文件系统。它将 `LowerDir` 和 `UpperDir` 合并为一个统一的文件系统视图。
|
||||
- **`WorkDir`**:是系统内部使用的临时目录,用于处理写时复制(CoW)和元数据操作。其内容在挂载时会被清空,且运行时不可见,一般不要动。
|
||||
|
||||
当启动一个容器时,Overlay2 会将镜像层(`LowerDir`)和容器层(`UpperDir`)联合挂载到 `MergedDir`,容器通过这个目录看到完整的文件系统。
|
||||
|
||||
## 实践案例1
|
||||
|
||||
通过 Overlay2 挂载目录,理解镜像层与容器层的交互逻辑。
|
||||
```shell
|
||||
# 1.目录结构 & 文件
|
||||
mkdir -p /mnt/overlay2/{lower,upper,work,merged}
|
||||
echo "基础文件内容" > /mnt/overlay2/lower/base.txt
|
||||
echo "初始配置" > /mnt/overlay2/lower/config.yaml
|
||||
# 2.挂载Overlay2
|
||||
mount -t overlay overlay \
|
||||
-o lowerdir=/mnt/overlay2/lower,upperdir=/mnt/overlay2/upper,workdir=/mnt/overlay2/work \
|
||||
/mnt/overlay2/merged
|
||||
# 3.模拟容器操作
|
||||
echo "容器修改内容" > /mnt/overlay2/merged/base.txt
|
||||
## CoW机制生效
|
||||
[root@master01 ~]# cat /mnt/overlay2/upper/base.txt
|
||||
容器修改内容
|
||||
[root@master01 ~]# cat /mnt/overlay2/lower/base.txt
|
||||
基础文件内容
|
||||
## 文件名 #40b 是 OverlayFS 在处理文件操作时生成的临时标识符,用于跟踪操作状态
|
||||
rm /mnt/overlay2/merged/config.yaml
|
||||
|
||||
# 卸载并清理
|
||||
umount /mnt/overlay2/merged
|
||||
rm -rf /mnt/overlay2/*
|
||||
```
|
||||
|
||||
## 实践案例2
|
||||
|
||||
验证运行容器的存储结构,并能快速定位。
|
||||
```shell
|
||||
# LowerDir、MergedDir、UpperDir、WorkDir
|
||||
[root@master01 ~]# docker inspect 379c14648fbb
|
||||
[root@master01 ~]# docker exec -it 3eb8f9c95ab4 touch /root/1.txt
|
||||
[root@master01 ~]# ls /var/lib/docker/overlay2/869a09f00704dbbb396d8be90d52b73870073c0a294deceac24a69afbe1a4310/diff/root/
|
||||
1.txt
|
||||
```
|
||||
|
||||
# 扩展阅读
|
||||
|
||||
存储引擎文档:
|
||||
https://docs.docker.com/storage/storagedriver/select-storage-driver/
|
||||
|
||||
存储引擎血案:
|
||||
https://www.cnblogs.com/youruncloud/p/5736718.html
|
124
Docker/Docker安装.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Docker服务端软件选择
|
||||
Docker CE(Community Edition,社区版)和 Docker EE(Enterprise Edition,企业版)是 Docker 产品的两个主要版本,它们之间的主要区别在于目标用户、功能集、支持和维护等方面:
|
||||
|
||||
| 对比项 | Docker CE | Docker EE |
|
||||
|--------|-----------|------------|
|
||||
| **目标用户** | 面向个人开发者、小团队以及技术爱好者,主要用于开发和测试环境 | 面向大型企业和组织,提供企业级的功能和支持 |
|
||||
| **功能集** | 提供基本的容器化功能,包括构建、运行和共享容器 | 除了包含 CE 版本的所有功能外,还提供了额外的企业级特性,如增强的安全、管理、可扩展性和集成性 |
|
||||
| **支持和维护** | 社区支持,适合自我解决问题的开发者 | 提供商业支持和专业服务,适合需要稳定运行环境的企业 |
|
||||
| **安全性** | 安全性相对较低,适合非生产环境 | 提供更高级的安全特性,如镜像扫描、安全策略和合规性报告 |
|
||||
| **管理** | 通常不需要复杂的管理工具 | 提供 Docker Universal Control Plane (UCP) 和 Docker Trusted Registry (DTR) 等管理工具,帮助企业更有效地管理容器环境 |
|
||||
| **成本** | 免费 | 需要购买许可证 |
|
||||
| **更新和生命周期** | 更新频繁,可能包含实验性功能,生命周期较短 | 更新周期更稳定,更注重稳定性和兼容性,生命周期较长 |
|
||||
|
||||
# Docker快速安装
|
||||
|
||||
```shell
|
||||
[root@docker-server ~]# chmod +x install_docker_ce.sh
|
||||
[root@docker-server ~]# ./install_docker_ce.sh
|
||||
```
|
||||
|
||||
# Docker快速使用
|
||||
|
||||
```shell
|
||||
# 拉取镜像
|
||||
[root@docker-server ~]# docker pull nginx
|
||||
# 启动容器
|
||||
[root@docker-server ~]# docker run --name nginx_container_test -d -p 8080:80 nginx
|
||||
# 进入容器
|
||||
[root@docker-server ~]# docker exec -it nginx_container_test bash
|
||||
echo 'docker nginx test' > /usr/share/nginx/html/index.html
|
||||
curl 192.168.88.10:8080
|
||||
# 查看容器
|
||||
[root@docker-server ~]# docker ps
|
||||
# 停止容器
|
||||
[root@docker-server ~]# docker stop nginx_container_test
|
||||
```
|
||||
|
||||
# Docker信息
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker info
|
||||
```
|
||||
|
||||
| 配置项 | 说明 |
|
||||
| :---| :---|
|
||||
| **容器状态信息** ||
|
||||
| Containers | 系统中所有容器的总数。包括运行中、已暂停和已停止的容器,用于整体容器资源评估 |
|
||||
| Running | 当前正在运行的容器数量。这些容器正常运行并提供服务,是系统负载的主要来源 |
|
||||
| Paused | 已暂停运行的容器数量。这些容器状态被临时冻结,通常用于调试或资源回收 |
|
||||
| Stopped | 已停止运行的容器数量。这些容器可能是任务完成或异常停止,需要定期清理 |
|
||||
| **系统基础信息** ||
|
||||
| Images | 本地已下载的Docker镜像总数。包括基础镜像、中间镜像和应用镜像,影响存储空间使用 |
|
||||
| Server Version | Docker引擎版本号。决定了可用特性和兼容性,建议在生产环境保持版本统一 |
|
||||
| **存储相关配置** ||
|
||||
| Storage Driver | 容器存储驱动类型(如overlay2、devicemapper)。影响容器I/O性能,推荐使用overlay2 |
|
||||
| Backing Filesystem | 底层文件系统类型(如ext4、xfs)。影响存储性能和可靠性,生产环境推荐使用xfs |
|
||||
| Supports d_type | 文件系统d_type支持状态。对overlay2驱动至关重要,确保启用以获得最佳性能 |
|
||||
| Native Overlay Diff | 原生Overlay差异存储支持。优化镜像层存储效率,减少磁盘空间占用 |
|
||||
| **日志与资源管理** ||
|
||||
| Logging Driver | 容器日志收集驱动(如json-file、syslog)。影响日志管理和问题排查能力 |
|
||||
| Cgroup Driver | 容器资源限制驱动(systemd/cgroupfs)。建议与系统init保持一致,避免资源管理冲突 |
|
||||
| **功能组件信息** ||
|
||||
| Plugins | Docker插件列表。包括存储、网络等扩展功能,按需启用以增强系统能力 |
|
||||
| Volume | 数据卷插件配置。用于持久化存储和容器间数据共享,确保数据可靠性 |
|
||||
| Network | 网络驱动类型。支持bridge、host、overlay等模式,根据应用场景选择 |
|
||||
| **运行时与安全** ||
|
||||
| Default Runtime | 默认容器运行时(通常为runc)。可选择其他OCI兼容运行时以满足特定需求 |
|
||||
| Security Options | 安全特性配置。包括AppArmor、SELinux等,建议在生产环境中启用以增强安全性 |
|
||||
| **系统资源信息** ||
|
||||
| Kernel Version | 内核版本信息。影响Docker功能和性能,建议使用推荐的内核版本 |
|
||||
| Operating System | 操作系统信息。包括发行版和版本号,影响兼容性和可用特性 |
|
||||
| Architecture | CPU架构类型。如x86_64、arm64,决定可用的容器镜像类型 |
|
||||
| CPUs | 可用CPU核心数。影响容器并发能力,建议预留部分资源给系统使用 |
|
||||
| Total Memory | 系统总内存。决定可分配给容器的最大内存,建议合理规划以避免资源竞争 |
|
||||
| **其他配置** ||
|
||||
| Docker Root Dir | Docker运行时根目录。存储容器和镜像数据,建议使用单独分区 |
|
||||
| Registry | 默认镜像仓库地址。用于拉取和推送镜像,可配置私有仓库加速访问 |
|
||||
| Experimental | 实验特性状态。包含未稳定功能,生产环境谨慎启用 |
|
||||
| Live Restore Enabled | 是否启用容器存活恢复功能,允许在Docker守护进程重启时保持容器运行|
|
||||
|
||||
|
||||
# 标准化组织OCI
|
||||
|
||||
容器技术是一种轻量级的虚拟化技术,用于隔离应用程序及其依赖项,使其能够在不同的环境中一致地运行。除了 Docker 之外,还有其他多种容器运行时和工具,例如 CoreOS 的 rkt、阿里的 Pouch 和红帽的 Podman。为了确保容器生态系统的标准性和可持续发展,Linux 基金会、Docker、微软、红帽、谷歌和 IBM 等公司在 2015 年 6 月共同成立了 **Open Container Initiative (OCI)** 组织。
|
||||
|
||||
## OCI目标
|
||||
|
||||
OCI 的主要目标是制定开放的容器规范,以确保不同容器技术之间的可移植性和互操作性。目前,OCI 已经发布了两个核心规范:
|
||||
|
||||
1. **Runtime Spec**:定义了容器运行时的规范,包括容器的生命周期管理、资源隔离和安全等。
|
||||
2. **Image Format Spec**:定义了容器镜像的格式和元数据,确保镜像可以在不同的容器运行时之间共享和运行。
|
||||
|
||||
通过遵循这些规范,不同的容器运行时和工具可以实现互操作性,从而推动容器技术的标准化和健康发展。
|
||||
|
||||
## 容器运行时
|
||||
|
||||
容器运行时是真正运行容器的地方,它需要与操作系统的内核紧密合作,为容器提供隔离的运行环境。以下是目前主流的三种容器运行时:
|
||||
|
||||
**1. LXC (Linux Containers)**
|
||||
|
||||
- **简介**:LXC 是 Linux 上早期的容器运行时,它利用 Linux 内核的 Namespace 和 Cgroups 技术来实现进程隔离和资源管理。
|
||||
- **特点**:
|
||||
- 提供了完整的 Linux 系统环境,支持多种 Linux 发行版。
|
||||
- 早期 Docker 也曾使用 LXC 作为其默认的运行时。
|
||||
- **适用场景**:适用于需要完整 Linux 系统环境的容器化应用。
|
||||
|
||||
**2. Runc**
|
||||
|
||||
- **简介**:Runc 是目前 Docker 默认的容器运行时,它是一个轻量级的命令行工具,用于运行和管理容器。
|
||||
- **特点**:
|
||||
- 完全遵循 OCI 的 Runtime Spec 规范,确保与 OCI 标准的兼容性。
|
||||
- 由于其轻量级和高性能的特点,Runc 已经成为许多容器运行时的底层实现。
|
||||
- **适用场景**:适用于需要高性能和轻量级容器运行环境的场景。
|
||||
|
||||
**3. Rkt (Rocket)**
|
||||
|
||||
- **简介**:Rkt 是由 CoreOS 开发的容器运行时,旨在提供一个安全、可靠且符合 OCI 规范的容器运行环境。
|
||||
- **特点**:
|
||||
- 与 Docker 不同,Rkt 本身是一个独立的容器运行时,不依赖 Docker 的守护进程。
|
||||
- 提供了更好的安全性和隔离性,例如通过 AppArmor 和 SELinux 等安全机制。
|
||||
- **适用场景**:适用于对安全性要求较高的容器化应用。
|
||||
|
||||
容器技术的发展离不开标准化的推动。OCI 通过制定 Runtime Spec 和 Image Format Spec,为容器运行时和工具提供了统一的标准,确保了不同容器技术之间的互操作性和可移植性。目前主流的容器运行时(如 LXC、Runc 和 Rkt)都遵循这些规范,从而推动了容器技术的广泛应用和发展。
|
||||
|
169
Docker/Docker容器管理.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# 容器
|
||||
|
||||
## 使用场景
|
||||
|
||||
开发一个杀手级的 Web 应用,它包含三个主要组件:React 前端、Python API 和 MySQL 数据库。如果你想开发这个项目,你必须安装 Node、Python 和 MySQL。
|
||||
|
||||
- **如何确保团队中开发人员使用的Python版本一致?**
|
||||
- **如何确保应用运行所需的版本不和现有生产环境版本冲突?**
|
||||
|
||||
什么是容器?独立进程。React 前端、Python API、MySQL 都在独立的环境中运行,并与其他组件完全隔离。
|
||||
|
||||
## 容器和虚拟机
|
||||
|
||||

|
||||
|
||||
| **虚拟化** | **容器** |
|
||||
| ------------------------------------------------ | ------------------------------------------------------- |
|
||||
| 隔离性强,有独立的GUEST OS | 共享内核和OS,隔离性弱! |
|
||||
| 虚拟化性能差(>15%) | 计算/存储无损耗,无Guest OS内存开销(~200M) |
|
||||
| 虚拟机镜像庞大(十几G~几十G), 且实例化时不能共享 | Docker容器镜象200~300M,且公共基础镜象实例化时可以共享 |
|
||||
| 虚拟机镜象缺乏统一标准 | Docker提供了容器应用镜象事实标准,OCI推动进一 步标准化 |
|
||||
| 虚拟机创建慢(>2分钟) | 秒级创建(<10s)相当于建立索引 |
|
||||
| 虚拟机启动慢(>30s) 读文件逐个加载 | 秒级(<1s,不含应用本身启动) |
|
||||
| 资源虚拟化粒度低,单机10~100虚拟机 | 单机支持1000+容器密度很高,适合大规模的部署 |
|
||||
|
||||
**对比总结**
|
||||
- **资源利用率更高**:一台物理机可以运行数百个容器,但一般只能运行数十个虚拟机。
|
||||
- **开销更小**:不需要启动单独的虚拟机占用硬件资源。
|
||||
- **启动速度更快**:可以在数秒内完成启动。
|
||||
|
||||
# 容器管理
|
||||
|
||||
## 创建容器
|
||||
|
||||
`Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker create -it --name nginx-test nginx bash
|
||||
```
|
||||
|
||||
## 启动容器
|
||||
|
||||
`Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker start nginx
|
||||
```
|
||||
|
||||
## 重启容器
|
||||
|
||||
`Usage: docker restart [OPTIONS] CONTAINER [CONTAINER...]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker restart nginx
|
||||
```
|
||||
|
||||
## 停止容器
|
||||
|
||||
`Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker stop nginx
|
||||
```
|
||||
|
||||
## 列出容器
|
||||
|
||||
`Usage: docker ps [OPTIONS]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker ps -a
|
||||
```
|
||||
|
||||
## 运行容器
|
||||
|
||||
`Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]`
|
||||
```shell
|
||||
# 等同于 create + start
|
||||
[root@docker-server ~]# docker run -it centos:latest bash
|
||||
|
||||
# 指定DNS
|
||||
[root@docker-server ~]# docker run -it --rm --dns 8.8.8.8 centos bash
|
||||
|
||||
# 端口映射
|
||||
## 前台启动随机映射端口
|
||||
[root@docker-server ~]# docker run -P nginx
|
||||
## 方式1,本地端口80映射到容器80端口
|
||||
[root@docker-server ~]# docker run -p 80:80 --name nginx-1 nginx:latest
|
||||
## 方式2,本地ip:本地端口:容器端口
|
||||
[root@docker-server ~]# docker run -p 192.168.204.135:80:80 --name nginx-1 nginx:latest
|
||||
## 方式3,本地ip:本地随机端口:容器端口
|
||||
[root@docker-server ~]# docker run -p 192.168.175.10::80 --name nginx-1 nginx:latest
|
||||
## 方式4,本地ip:本地端口:容器端口/协议默认为tcp协议
|
||||
[root@docker-server ~]# docker run -p 192.168.175.10:80:80/tcp --name nginx-1 nginx:latest
|
||||
## 查看容器已经映射的端口
|
||||
[root@docker-server ~]# docker port nginx-1
|
||||
|
||||
# 传递运行命令
|
||||
[root@docker-server ~]# docker run -it centos:latest /bin/bash
|
||||
[root@docker-server ~]# docker run -it centos:latest cat /etc/hosts
|
||||
|
||||
# 单次运行,容器退出后自动删除
|
||||
[root@docker-server ~]# docker run --name hello_world_test --rm hello-world
|
||||
|
||||
# 后台运行
|
||||
[root@docker-server ~]# docker run -d -P --name nginx-2 nginx
|
||||
```
|
||||
|
||||
**参数说明:**
|
||||
|
||||
| 选项 | 说明 |
|
||||
|:---|:---|
|
||||
| -d | 以守护进程方式在后台运行容器。默认为否,适用于运行需要持续在线的服务 |
|
||||
| -i | 保持标准输入打开,即使未连接也保持STDIN打开,常与-t一起使用 |
|
||||
| -P | 通过NAT机制将容器标记暴露的端口自动映射到主机的随机临时端口 |
|
||||
| -p | 手动指定容器端口映射,格式:主机(宿主)端口:容器端口 |
|
||||
| -t | 分配一个伪终端(pseudo-TTY),通常与-i配合使用,以提供交互式shell |
|
||||
| -v | 挂载主机上的文件卷到容器内,格式:主机目录:容器目录[:权限] |
|
||||
| --rm | 容器退出后自动删除容器(不能与-d同时使用),适用于临时测试场景 |
|
||||
| -e | 设置容器内的环境变量,格式:-e 变量名=变量值 |
|
||||
| -h | 指定容器的主机名,便于容器间通过主机名访问 |
|
||||
| --name | 指定容器的别名,方便管理和访问容器 |
|
||||
| --cpu-shares | 设置容器使用CPU的相对权重(默认1024),数值越高优先级越高 |
|
||||
| --cpuset-cpus | 限制容器使用特定的CPU核心,如:0-3(使用前4个核心)或0,2(使用第1、3核心) |
|
||||
| -m | 限制容器可使用的最大内存量,支持的单位:b、k、m、g,如:-m 512m
|
||||
|
||||
|
||||
## 挂起/恢复容器
|
||||
|
||||
`Usage: docker pause CONTAINER [CONTAINER...]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker pause nginx-2
|
||||
```
|
||||
`Usage: docker unpause CONTAINER [CONTAINER...]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker unpause nginx-2
|
||||
```
|
||||
|
||||
## 进入容器
|
||||
|
||||
`Usage: docker exec [OPTIONS] CONTAINER`
|
||||
```shell
|
||||
[root@docker-server ~]# docker exec -it nginx-2 bash
|
||||
# attach不推荐: 所有使用此方式进入容器的操作都是同步显示的且exit容器将被关闭,且使用exit退出后容器关闭
|
||||
[root@docker-server ~]# docker attach nginx-2
|
||||
# nsenter: 通过pid进入到容器内部,不过可以使用docker inspect获取到容器的pid
|
||||
[root@docker-server ~]# nsenter -t $(docker inspect -f "[.State.Pid]" nginx-2) -m -u -i -n -p
|
||||
```
|
||||
|
||||
## 导入/导出容器
|
||||
|
||||
`Usage: docker export [OPTIONS] CONTAINER`
|
||||
```shell
|
||||
[root@docker-server ~]# docker export -o /opt/nginx.tar nginx-2
|
||||
```
|
||||
`Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker import /opt/nginx.tar nginx:v50
|
||||
```
|
||||
|
||||
**适用场景:** 主要用来制作基础镜像,比如从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export保存为一个基础镜像。然后把这个镜像分发给其他人使用,作为基础的开发环境。(因为export导出的镜像只会保留从镜像运行到export之间对文件系统的修改,所以只适合做基础镜像)
|
||||
|
||||
## 查看容器日志
|
||||
|
||||
`Usage: docker logs [OPTIONS] CONTAINER`
|
||||
```shell
|
||||
[root@docker-server ~]# docker logs nginx-2
|
||||
```
|
||||
|
||||
## 删除容器
|
||||
|
||||
`Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]`
|
||||
```shell
|
||||
[root@docker-server ~]# docker rm -f nginx-2
|
||||
```
|
518
Docker/Docker容器编排.md
Normal file
@@ -0,0 +1,518 @@
|
||||
# Docker compose单机编排
|
||||
|
||||
## Docker Compose 简介
|
||||
|
||||
当在宿主机上启动多个容器时,手动操作会比较繁琐,且容易出错。在这种情况下,推荐使用 Docker 单机编排工具 **Docker Compose**。Docker Compose 是 Docker 官方提供的一个开源工具,用于管理和编排多个容器。它可以解决容器之间的依赖关系,简化容器的创建、启动和停止操作。
|
||||
|
||||
例如,启动一个 Nginx 前端服务时,可能需要调用后端的 Tomcat 服务,而 Tomcat 容器又依赖于数据库。在这种嵌套依赖关系中,Docker Compose 可以按照正确的顺序启动这些容器,确保每个容器在启动时都能正确依赖所需的其他容器。因此,Docker Compose 完全可以替代 `docker run` 来创建和管理容器。
|
||||
|
||||
## Docker Compose 项目结构
|
||||
|
||||
Docker Compose 项目将所管理的容器分为三层,分别是:
|
||||
|
||||
- **工程(Project)**:工程是 Docker Compose 管理的最高层级,通常对应一个包含多个服务的应用场景。一个工程可以包含多个服务,这些服务通过 `docker-compose.yml` 文件进行定义。
|
||||
- **服务(Service)**:服务是工程中的一个逻辑单元,通常对应一个容器模板。服务定义了容器的镜像、环境变量、端口映射等配置。一个服务可以启动多个容器实例。
|
||||
- **容器(Container)**:容器是服务的具体运行实例。Docker Compose 会根据服务的定义创建并管理容器。
|
||||
|
||||
通过这种分层结构,Docker Compose 能够高效地管理和编排多个容器,简化复杂的容器依赖关系,提高开发和部署效率。
|
||||
|
||||
# 基础环境准备
|
||||
|
||||
## Docker compose部署
|
||||
|
||||
yum安装docker-compese
|
||||
|
||||
从 Docker 20.10 版本开始,Docker Compose 被集成到了 Docker 中,作为插件使用,而不是独立的命令行工具,所以说在20以后的版本中,我们直接使用docker compose(中间用空格隔开)即可
|
||||
|
||||
```bash
|
||||
# 旧版本中安装docker-compose的方式
|
||||
[root@localhost ~]# yum install -y epel-release
|
||||
[root@localhost ~]# yum install docker-compose.noarch -y
|
||||
[root@localhost ~]# docker-compose version
|
||||
docker-compose version 1.18.0, build 8dd22a9
|
||||
docker-py version: 2.6.1
|
||||
CPython version: 3.6.8
|
||||
OpenSSL version: OpenSSL 1.0.2k-fips 26 Jan 2017
|
||||
```
|
||||
|
||||
## 相关参数
|
||||
|
||||
```bash
|
||||
# docker-compose --help
|
||||
|
||||
Define and run multi-container applications with Docker.
|
||||
|
||||
## Usage
|
||||
```bash
|
||||
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
|
||||
docker-compose -h|--help
|
||||
```
|
||||
|
||||
### 选项说明
|
||||
|
||||
- `-f`, `--file FILE`:指定 Compose 模板文件,默认为 `docker-compose.yml`。
|
||||
- `-p`, `--project-name NAME`:指定项目名称,默认将使用当前所在目录名称作为项目名。
|
||||
- `--verbose`:显示更多输出信息。
|
||||
- `--log-level LEVEL`:定义日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)。
|
||||
- `--no-ansi`:不显示 ANSI 控制字符。
|
||||
- `-v`, `--version`:显示版本。
|
||||
|
||||
### 命令选项
|
||||
|
||||
以下命令需要在 `docker-compose.yml` 或 `yaml` 文件所在目录里执行。
|
||||
|
||||
- `build`:构建或重新构建服务中定义的镜像。
|
||||
- `bundle`:从当前 `docker-compose` 文件生成一个以 `<当前目录>` 为名称的 JSON 格式的 Docker Bundle 文件,用于离线部署。
|
||||
- `config -q`:验证 Compose 文件格式是否正确,若无错误则不输出任何内容。
|
||||
- `create`:创建服务所需的所有容器,但不启动它们。
|
||||
- `down`:停止和删除所有容器、网络、卷,以及由 `docker-compose up` 创建的镜像(可选)。
|
||||
- `events`:实时显示容器的日志事件,支持指定日志格式(如 JSON)。
|
||||
- `exec`:在指定的容器中运行一个命令。
|
||||
- `help`:显示指定命令的帮助信息。
|
||||
- `images`:列出所有由 `docker-compose` 创建的镜像。
|
||||
- `kill`:强制终止正在运行的容器。
|
||||
- `logs`:查看容器的日志输出。
|
||||
- `pause`:暂停服务中的所有容器。
|
||||
- `port`:查看服务的端口映射情况。
|
||||
- `ps`:列出所有由 `docker-compose` 管理的容器。
|
||||
- `pull`:从镜像仓库拉取服务中定义的镜像。
|
||||
- `push`:将服务中定义的镜像推送到镜像仓库。
|
||||
- `restart`:重启服务中的所有容器。
|
||||
- `rm`:删除所有已停止的容器。
|
||||
- `run`:在指定服务中运行一个命令,创建一个临时容器。
|
||||
- `scale`:设置指定服务运行的容器数量。
|
||||
- `start`:启动已创建但未运行的服务。
|
||||
- `stop`:停止正在运行的服务。
|
||||
- `top`:显示正在运行的容器的进程信息。
|
||||
- `unpause`:恢复之前暂停的服务。
|
||||
- `up`:构建、创建并启动所有服务,如果服务已存在则重新启动。
|
||||
|
||||
### 示例 `docker-compose.yml` 文件
|
||||
|
||||
以下是一个详细的 `docker-compose.yml` 文件示例,包含注释和可能用到的所有指令。这个示例展示了如何定义一个包含多个服务(如 Nginx、Tomcat 和 MySQL)的 Docker Compose 项目。
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
|
||||
# 定义版本,指定 Compose 文件的格式版本
|
||||
version: '3.8'
|
||||
|
||||
# 定义服务
|
||||
services:
|
||||
# 定义 MySQL 服务
|
||||
mysql:
|
||||
# 使用的镜像名称
|
||||
image: mysql:5.7
|
||||
# 容器的名称
|
||||
container_name: mysql_container
|
||||
# 环境变量,用于设置 MySQL 的 root 密码
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: mypassword
|
||||
MYSQL_DATABASE: mydb
|
||||
# 持久化数据卷
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
# 端口映射,将宿主机的 3306 端口映射到容器的 3306 端口
|
||||
ports:
|
||||
- "3306:3306"
|
||||
# 重启策略,始终重启
|
||||
restart: always
|
||||
# 网络配置,连接到默认网络
|
||||
networks:
|
||||
- my_network
|
||||
|
||||
# 定义 Tomcat 服务
|
||||
tomcat:
|
||||
# 使用的镜像名称
|
||||
image: tomcat:9.0
|
||||
# 容器的名称
|
||||
container_name: tomcat_container
|
||||
# 环境变量,设置 Tomcat 的一些配置
|
||||
environment:
|
||||
- CATALINA_OPTS=-Xms512M -Xmx1024M
|
||||
# 持久化 Tomcat 的 webapps 目录
|
||||
volumes:
|
||||
- tomcat_webapps:/usr/local/tomcat/webapps
|
||||
# 端口映射,将宿主机的 8080 端口映射到容器的 8080 端口
|
||||
ports:
|
||||
- "8080:8080"
|
||||
# 依赖关系,确保 MySQL 服务先启动
|
||||
depends_on:
|
||||
- mysql
|
||||
# 重启策略,始终重启
|
||||
restart: always
|
||||
# 网络配置,连接到默认网络
|
||||
networks:
|
||||
- my_network
|
||||
|
||||
# 定义 Nginx 服务
|
||||
nginx:
|
||||
# 使用的镜像名称
|
||||
image: nginx:1.19
|
||||
# 容器的名称
|
||||
container_name: nginx_container
|
||||
# 持久化 Nginx 的配置文件和静态资源
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./html:/usr/share/nginx/html
|
||||
# 端口映射,将宿主机的 80 端口映射到容器的 80 端口
|
||||
ports:
|
||||
- "80:80"
|
||||
# 依赖关系,确保 Tomcat 服务先启动
|
||||
depends_on:
|
||||
- tomcat
|
||||
# 重启策略,始终重启
|
||||
restart: always
|
||||
# 网络配置,连接到默认网络
|
||||
networks:
|
||||
- my_network
|
||||
|
||||
# 定义卷
|
||||
volumes:
|
||||
# 定义 MySQL 数据卷
|
||||
mysql_data:
|
||||
driver: local
|
||||
# 定义 Tomcat webapps 卷
|
||||
tomcat_webapps:
|
||||
driver: local
|
||||
|
||||
# 定义网络
|
||||
networks:
|
||||
# 定义默认网络
|
||||
my_network:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
### 文件说明
|
||||
|
||||
1. **版本**:
|
||||
- `version: '3.8'`:指定 Compose 文件的格式版本。不同的版本支持不同的功能和语法。
|
||||
2. **服务**:
|
||||
- `services`:定义项目中包含的所有服务。
|
||||
- 每个服务(如 `mysql`、`tomcat`、`nginx`)都有自己的配置,包括:
|
||||
- `image`:指定使用的 Docker 镜像。
|
||||
- `container_name`:指定容器的名称。
|
||||
- `environment`:设置环境变量。
|
||||
- `volumes`:定义数据卷,用于持久化数据或挂载本地文件。
|
||||
- `ports`:定义端口映射。
|
||||
- `depends_on`:定义服务之间的依赖关系。
|
||||
- `restart`:设置重启策略。
|
||||
- `networks`:定义服务所属的网络。
|
||||
3. **卷**:
|
||||
- `volumes`:定义数据卷,用于持久化数据。这里定义了两个卷:`mysql_data` 和 `tomcat_webapps`。
|
||||
4. **网络**:
|
||||
- `networks`:定义网络,用于服务之间的通信。这里定义了一个默认的桥接网络 `my_network`。
|
||||
|
||||
### 可能用到的 Docker Compose 命令
|
||||
|
||||
以下是在 `docker-compose.yml` 文件所在目录中可以执行的常用命令:
|
||||
|
||||
- **`docker-compose up`**:构建、创建并启动所有服务。如果服务已存在,则重新启动。
|
||||
- **`docker-compose down`**:停止并删除所有容器、网络、卷以及由 `docker-compose up` 创建的镜像(可选)。
|
||||
- **`docker-compose build`**:构建或重新构建服务中定义的镜像。
|
||||
- **`docker-compose create`**:创建服务所需的所有容器,但不启动它们。
|
||||
- **`docker-compose start`**:启动已创建但未运行的服务。
|
||||
- **`docker-compose stop`**:停止正在运行的服务。
|
||||
- **`docker-compose restart`**:重启服务中的所有容器。
|
||||
- **`docker-compose kill`**:强制终止正在运行的容器。
|
||||
- **`docker-compose rm`**:删除所有已停止的容器。
|
||||
- **`docker-compose logs`**:查看容器的日志输出。
|
||||
- **`docker-compose exec`**:在指定的容器中运行一个命令。
|
||||
- **`docker-compose ps`**:列出所有由 `docker-compose` 管理的容器。
|
||||
- **`docker-compose config`**:验证 Compose 文件格式是否正确,若无错误则不输出任何内容。
|
||||
- **`docker-compose bundle`**:从当前 `docker-compose` 文件生成一个 JSON 格式的 Docker Bundle 文件,用于离线部署。
|
||||
- **`docker-compose pull`**:从镜像仓库拉取服务中定义的镜像。
|
||||
- **`docker-compose push`**:将服务中定义的镜像推送到镜像仓库。
|
||||
- **`docker-compose scale`**:设置指定服务运行的容器数量。
|
||||
|
||||
# 实战案例
|
||||
|
||||
## 启动单个容器
|
||||
|
||||
一、编写docker-compose文件
|
||||
|
||||
```yaml
|
||||
[root@localhost ~]# mkdir -pv docker-compose/nginx
|
||||
[root@localhost ~]# cd docker-compose/nginx
|
||||
[root@localhost nginx]# pwd
|
||||
/root/docker-compose/nginx
|
||||
[root@localhost nginx]# vim docker-compose.yml
|
||||
# docker-compose.yml
|
||||
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
container_name: nginx_web1
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- /data/web:/usr/share/nginx/html
|
||||
```
|
||||
|
||||
二、启动容器
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker compose up -d
|
||||
[+] Running 2/2
|
||||
✔ Network nginx_default Created 0.0s
|
||||
✔ Container nginx_web1 Started 0.2s
|
||||
[root@localhost nginx]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
09d091a0c1a1 nginx "/docker-entrypoint.…" 29 seconds ago Up 28 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp nginx_web1
|
||||
|
||||
# 不指定网络的话,会默认创建一个类型为bridge的网络
|
||||
[root@localhost nginx]# docker network ls
|
||||
NETWORK ID NAME DRIVER SCOPE
|
||||
36f9c2f8e090 bridge bridge local
|
||||
93ffe4510dd0 host host local
|
||||
d0456365c64d nginx_default bridge local
|
||||
61f0d0d9b051 none null local
|
||||
```
|
||||
|
||||
三、访问测试
|
||||
|
||||
|
||||
## 启动多个容器
|
||||
|
||||
一、编辑docker-compose文件
|
||||
|
||||
```bash
|
||||
[root@localhost docker]# cat docker-compose.yml
|
||||
service-nginx:
|
||||
image: nginx
|
||||
container_name: nginx_web1
|
||||
ports:
|
||||
- "80:80"
|
||||
|
||||
service-tomcat:
|
||||
image: tomcat
|
||||
container_name: tomcat_web1
|
||||
ports:
|
||||
- "8080:8080"
|
||||
[root@localhost docker]# docker-compose up -d
|
||||
nginx_web1 /docker-entrypoint.sh ngin ... Up 0.0.0.0:80->80/tcp,:::80->80/tcp
|
||||
tomcat_web1 catalina.sh run Up 0.0.0.0:8080->8080/tcp,:::8080-
|
||||
>8080/tcp
|
||||
```
|
||||
|
||||
## 定义数据卷挂载
|
||||
|
||||
- 创建数据卷目录和文件
|
||||
|
||||
```bash
|
||||
[root@localhost docker]# mkdir -p /data/nginx
|
||||
[root@localhost docker]# echo 'docker nginx' > /data/nginx/index.html
|
||||
```
|
||||
|
||||
- 编辑配置文件
|
||||
|
||||
```bash
|
||||
[root@localhost docker]# cat docker-compose.yml
|
||||
service-nginx:
|
||||
image: nginx
|
||||
container_name: nginx_web1
|
||||
volumes:
|
||||
- /data/nginx/:/usr/share/nginx/html
|
||||
ports:
|
||||
- "80:80"
|
||||
|
||||
service-tomcat:
|
||||
image: tomcat
|
||||
container_name: tomcat_web1
|
||||
ports:
|
||||
- "8080:8080"
|
||||
```
|
||||
|
||||
- 访问测试
|
||||
|
||||
```bash
|
||||
[root@localhost docker]# curl localhost
|
||||
docker nginx
|
||||
```
|
||||
|
||||
# Docker Compose部署LNMP实战
|
||||
|
||||
## 部署LNMP环境
|
||||
|
||||
- 使用docker-compose实现编排nginx+phpfpm+mysql容器
|
||||
- 部署一个博客系统
|
||||
- 首先编写一个如下的配置文件
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
image: nginx:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
volumes:
|
||||
- /data/lnmp/nginx/conf.d:/etc/nginx/conf.d
|
||||
- /data/lnmp/nginx/html:/usr/share/nginx/html
|
||||
- /data/lnmp/nginx/log:/var/log/nginx
|
||||
depends_on:
|
||||
- php
|
||||
- mysql
|
||||
networks:
|
||||
- lnmp-network
|
||||
php:
|
||||
image: php:7.4-fpm
|
||||
restart: always
|
||||
volumes:
|
||||
- /data/lnmp/nginx/html:/usr/share/nginx/html
|
||||
networks:
|
||||
- lnmp-network
|
||||
depends_on:
|
||||
- mysql
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
restart: always
|
||||
volumes:
|
||||
- /data/lnmp/dbdata:/var/lib/mysql
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: "123456"
|
||||
MYSQL_DATABASE: login
|
||||
networks:
|
||||
- lnmp-network
|
||||
networks:
|
||||
lnmp-network:
|
||||
driver: bridge
|
||||
volumes:
|
||||
dbdata: null
|
||||
```
|
||||
|
||||
运行docker-compose.yml
|
||||
|
||||
```bash
|
||||
[root@localhost lnmp]# docker compose up -d
|
||||
[root@localhost lnmp]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
825b8630de47 nginx:latest "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp lnmp-web-1
|
||||
d1d6339ba0d7 lnmp-php "docker-php-entrypoi…" 4 minutes ago Up 4 minutes 9000/tcp lnmp-php-1
|
||||
109672c0b1f0 mysql:5.7 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 3306/tcp, 33060/tcp lnmp-mysql-1
|
||||
```
|
||||
|
||||
在 `/data/lnmp/nginx/conf.d/default.conf` 中写入nginx 的配置文件
|
||||
|
||||
```shell
|
||||
server {
|
||||
listen 80;
|
||||
root /usr/share/nginx/html;
|
||||
location / {
|
||||
index index.php index.html;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
准备探针测试
|
||||
|
||||
在 `/data/lnmp/nginx/html/info.php` 中准备php探针
|
||||
|
||||
```shell
|
||||
<?php
|
||||
phpinfo();
|
||||
?>
|
||||
```
|
||||
|
||||
测试数据库连接
|
||||
|
||||
在`/data/lnmp/nginx/html/mysql.php`中准备php探针
|
||||
|
||||
```shell
|
||||
<?php
|
||||
$dbhost = "mysql";
|
||||
$dbuser = "root";
|
||||
$dbpass = "123456";
|
||||
$db = "login";
|
||||
$conn = mysqli_connect($dbhost, $dbuser, $dbpass, $db) or exit("数据库连接失败!");
|
||||
echo "数据库连接成功";
|
||||
?>
|
||||
```
|
||||
|
||||
访问测试后发现,连接mysql报错,提示找不到mysqli_connect(),看来是官方构建的php没有mysqli模块
|
||||
|
||||
所以我们需要定制带有mysqli模块的php,编写如下dockerfile
|
||||
|
||||
```shell
|
||||
FROM php:7.4-fpm
|
||||
ENV TZ=Asia/Shanghai
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
|
||||
&& sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
|
||||
&& sed -i -e 's|security.debian.org/\? |security.debian.org/debian-security |g' \
|
||||
-e 's|security.debian.org|mirrors.ustc.edu.cn|g' \
|
||||
-e 's|deb.debian.org/debian-security|mirrors.ustc.edu.cn/debian-security|g' \
|
||||
/etc/apt/sources.list \
|
||||
&& apt-get update && apt-get install -y \
|
||||
libfreetype6-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng-dev \
|
||||
&& docker-php-ext-configure gd -with-freetype -with-jpeg \
|
||||
&& docker-php-ext-install -j$(nproc) gd mysqli && docker-php-ext-enable mysqli
|
||||
```
|
||||
|
||||
然后修改 docker-compose.yml 文件如下
|
||||
|
||||
```yaml
|
||||
# docker-compose build lnmp
|
||||
|
||||
services:
|
||||
web:
|
||||
image: nginx:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
volumes:
|
||||
- /data/lnmp/nginx/conf.d:/etc/nginx/conf.d
|
||||
- /data/lnmp/nginx/html:/usr/share/nginx/html
|
||||
- /data/lnmp/nginx/log:/var/log/nginx
|
||||
depends_on:
|
||||
- php
|
||||
- mysql
|
||||
networks:
|
||||
- lnmp-network
|
||||
php:
|
||||
# image: dockerfile:php:7.4-fpm
|
||||
# 这里来让compose自动构建,指定dockerfile的文件位置即可
|
||||
build:
|
||||
context: .
|
||||
dockerfile: dockerfile
|
||||
restart: always
|
||||
volumes:
|
||||
- /data/lnmp/nginx/html:/usr/share/nginx/html
|
||||
networks:
|
||||
- lnmp-network
|
||||
depends_on:
|
||||
- mysql
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
restart: always
|
||||
volumes:
|
||||
- /data/lnmp/dbdata:/var/lib/mysql
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: "123456"
|
||||
MYSQL_DATABASE: login
|
||||
networks:
|
||||
- lnmp-network
|
||||
networks:
|
||||
lnmp-network:
|
||||
driver: bridge
|
||||
volumes:
|
||||
dbdata: null
|
||||
```
|
||||
|
||||
测试验证
|
||||
|
||||
```shell
|
||||
[root@localhost lnmp]# docker compose up -d
|
||||
[root@localhost lnmp]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
825b8630de47 nginx:latest "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp lnmp-web-1
|
||||
d1d6339ba0d7 lnmp-php "docker-php-entrypoi…" 4 minutes ago Up 4 minutes 9000/tcp lnmp-php-1
|
||||
109672c0b1f0 mysql:5.7 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 3306/tcp, 33060/tcp lnmp-mysql-1
|
||||
```
|
91
Docker/Docker数据管理.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# 存储
|
||||
## 介绍
|
||||
默认情况下,容器内创建的所有文件都存储在可写的容器层上,该层位于只读、不可变的图像层之上。
|
||||
|
||||
写入容器层的数据在容器销毁后不会保留。这意味着,如果其他进程需要这些数据,则很难将其从容器中取出。
|
||||
|
||||
每个容器的可写层都是唯一的。无法将数据从可写层提取到主机或其他容器。
|
||||
|
||||
## 存储挂载选项
|
||||
|
||||
| 挂载类型 | 说明 | 使用场景 | 特点 |
|
||||
|:---------|:-----|:---------|:-----|
|
||||
| Volume Mounts | Docker管理的持久化数据卷,存储在/var/lib/docker/volumes/目录下 | 数据库存储、应用数据持久化 | 独立于容器生命周期、可在容器间共享、支持数据备份和迁移 |
|
||||
| Bind Mounts | 将宿主机目录或文件直接挂载到容器内 | 开发环境代码热更新、配置文件挂载 | 方便直接操作文件、依赖宿主机文件系统、适合开发调试 |
|
||||
| Tmpfs Mounts | 将数据临时存储在宿主机内存中 | 敏感数据存储、临时文件存储 | 高性能、数据易失性、增加内存占用 |
|
||||
| Named Pipes | 在容器间建立命名管道进行通信 | 容器间进程通信、数据流传输 | 低延迟、进程间通信、适合流式数据传输 |
|
||||
|
||||
# Volume mounts
|
||||
## 管理操作
|
||||
`Usage: docker volume create [OPTIONS] [VOLUME]`
|
||||
`Usage: docker volume ls [OPTIONS]`
|
||||
`Usage: docker volume inspect [OPTIONS] VOLUME [VOLUME...]`
|
||||
`Usage: docker volume rm [OPTIONS] VOLUME [VOLUME...]`
|
||||
`Usage: docker volume prune [OPTIONS]`
|
||||
```shell
|
||||
|
||||
```
|
||||
|
||||
## 使用卷启动容器
|
||||
如果使用不存在的卷启动容器,Docker 会为创建该卷。
|
||||
|
||||
`Usage: docker run --mount type=volume[,src=<volume-name>],dst=<mount-path>[,<key>=<value>...]`
|
||||
|
||||
| 参数 | 说明 | 使用示例 | 最佳实践 |
|
||||
|:---------|:-----|:---------|:---------|
|
||||
| source, src | 卷的名称,用于指定要挂载的数据卷 | `src=myvolume` | 使用有意义的名称便于识别和管理 |
|
||||
| target, dst | 容器内的挂载路径,指定数据卷挂载到容器内的位置 | `dst=/data/app` | 遵循容器内标准目录结构 |
|
||||
| type | 卷的类型,可选值:volume、bind、tmpfs,默认为volume | `type=volume` | 根据数据持久化需求选择合适类型 |
|
||||
| readonly, ro | 只读挂载标志,设置后容器内无法修改挂载内容 | `ro=true` | 对配置文件等静态内容建议只读挂载 |
|
||||
| volume-subpath | 卷的子路径,只挂载数据卷中的指定子目录 | `volume-subpath=/config` | 用于精确控制挂载范围,提高安全性 |
|
||||
| volume-opt | 卷的额外选项,用于指定卷的特定行为 | `volume-opt=size=10G` | 根据实际需求配置,避免过度使用 |
|
||||
| volume-nocopy | 创建卷时不从容器复制数据 | `volume-nocopy=true` | 用于避免不必要的数据复制,提高性能 |
|
||||
|
||||
```shell
|
||||
docker run -d --name devtest --mount source=myvol2,target=/app nginx:latest
|
||||
```
|
||||
|
||||
`Usage: docker run -v [<volume-name>:]<mount-path>[:opts]`
|
||||
```shell
|
||||
docker run -d --name devtest -v myvol2:/app nginx:latest
|
||||
```
|
||||
|
||||
## 实践案例
|
||||
**需求**:运行MySQL容器并支持久化存储,进行一次数据备份,数据恢复测试验证。
|
||||
|
||||
```shell
|
||||
|
||||
```
|
||||
|
||||
# Bind mounts
|
||||
使用绑定挂载时,主机上的文件或目录将从主机挂载到容器中。
|
||||
|
||||
如果将目录绑定挂载到容器上的非空目录中,则目录的现有内容被绑定挂载隐藏。
|
||||
|
||||
## 使用绑定挂载启动容器
|
||||
```shell
|
||||
Usage:
|
||||
docker run --mount type=bind,src=<host-path>,dst=<container-path>[,<key>=<value>...]
|
||||
docker run -v <host-path>:<container-path>[:opts]
|
||||
```
|
||||
|
||||
| 参数 | 说明 | 使用场景 | 最佳实践 |
|
||||
|:---------|:-----|:---------|:---------|
|
||||
| readonly, ro | 将挂载点设置为只读模式,容器内无法修改挂载的内容 | 配置文件、静态资源文件挂载 | 对于不需要容器内修改的内容,建议使用只读模式增加安全性 |
|
||||
| rprivate | 使挂载点的挂载事件不会传播到其他挂载点 | 默认的挂载传播模式 | 适用于大多数场景,确保挂载隔离性 |
|
||||
| rshared | 使挂载点的挂载事件双向传播 | 需要在多个挂载点间共享挂载事件的场景 | 谨慎使用,可能影响容器隔离性 |
|
||||
| rslave | 使挂载点的挂载事件单向传播(从主机到容器) | 需要容器感知主机挂载变化的场景 | 在特定场景下使用,如动态存储管理 |
|
||||
| rbind | 递归绑定挂载,包含所有子目录 | 需要完整复制目录结构的场景 | 确保目录结构完整性,但注意性能开销 |
|
||||
|
||||
|
||||
## 实践案例
|
||||
**需求**:启动Nginx容器并挂载宿主机nginx配置文件和主页目录,容器内无权限修改相关内容,测试验证。
|
||||
|
||||
```shell
|
||||
|
||||
```
|
||||
|
||||
# 扩展阅读
|
||||
tmpfs mounts: https://docs.docker.com/engine/storage/tmpfs/
|
||||
|
||||
volumes plugins: https://docs.docker.com/engine/extend/legacy_plugins/
|
69
Docker/Docker网络管理.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# 网络
|
||||
容器网络是指容器能够连接和通信的能力,无论是容器之间还是与外部。
|
||||
|
||||
# 用户自定义网络
|
||||
可以创建自定义的用户定义网络,并将多个容器连接到同一网络。一旦连接到用户定义的网络,容器可以使用容器 IP 地址或容器名称相互通信。
|
||||
|
||||
`Usage: docker network create [OPTIONS] NETWORK`
|
||||
```shell
|
||||
# 使用bridge网络驱动创建网络并启动容器
|
||||
docker network create -d bridge my-net
|
||||
docker run --network=my-net -itd --name=container1 busybox
|
||||
docker run --network=my-net -itd --name=container2 busybox
|
||||
# 测试网络连接
|
||||
[root@master01 ~]# docker exec -it container1 ping www.baidu.com
|
||||
[root@master01 ~]# docker exec -it container1 cat /etc/hosts | grep 172
|
||||
172.19.0.3 1adf81f08c86
|
||||
[root@master01 ~]# docker exec -it container1 ping container2
|
||||
```
|
||||
# 网络驱动
|
||||
Docker服务安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡,其ip地址都是172.17.0.1/16,并且会生成三种不同类型的网络。
|
||||
|
||||
```shell
|
||||
[root@master01 ~]# docker network ls
|
||||
NETWORK ID NAME DRIVER SCOPE
|
||||
fe2c2cabeff7 bridge bridge local
|
||||
459b4a9926ed host host local
|
||||
526baa2eb8f6 none null local
|
||||
```
|
||||
|
||||
| Docker网络模式 | 配置 | 说明 | 使用场景 |
|
||||
|--------------|------|------|----------------|
|
||||
| host模式 | --net=host | 容器和宿主机共享Network namespace,直接使用宿主机网络栈。容器不会获得独立的Network namespace,也不会配置独立的IP和端口。性能开销最小,但缺少网络隔离。 | 适用于对网络性能要求极高的场景,如高性能计算、流媒体服务等
|
||||
| container模式 | --net=container:NAME_or_ID | 容器和指定的容器共享Network namespace。新容器使用已存在容器的网络栈,共享IP地址和端口范围。保持了其他资源(如文件系统、进程等)的隔离。 | 最典型应用是Kubernetes的Pod实现
|
||||
| none模式 | --net=none | 容器拥有独立的Network namespace,但不做任何网络配置。容器没有网卡、IP、路由等网络配置,需要手动配置网络。 | 适用于对安全性要求极高的场景
|
||||
| bridge模式 | --net=bridge | 默认网络模式。Docker daemon创建docker0虚拟网桥,通过veth pair连接容器,实现容器间的通信。支持端口映射和地址转换,提供基本的网络隔离。 | 最常用的网络模式
|
||||
|
||||
# 工作原理
|
||||
## none网络类型
|
||||

|
||||
|
||||
## container网络类型
|
||||

|
||||
|
||||
|
||||
## host网络类型
|
||||

|
||||
|
||||
|
||||
## bridge网络类型
|
||||

|
||||
|
||||
**veth pair 对应关系**
|
||||
```shell
|
||||
[root@master01 ~]# ip link show | grep veth0f | awk '{print $1,$2}'
|
||||
40: veth0fbbd68@if39
|
||||
[root@master01 ~]# cat /sys/class/net/veth0fbbd68/ifindex
|
||||
40
|
||||
[root@master01 ~]# cat /sys/class/net/veth0fbbd68/iflink
|
||||
39
|
||||
[root@master01 ~]# docker exec -it container1 ip link show eth0
|
||||
39: eth0@if40: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
|
||||
link/ether 02:42:ac:13:00:03 brd ff:ff:ff:ff:ff:ff
|
||||
```
|
||||
|
||||
|
||||
# 扩展阅读
|
||||
数据包过滤和防火墙: https://docs.docker.com/engine/network/packet-filtering-firewalls/
|
||||
|
||||
网络驱动:https://docs.docker.com/engine/network/drivers/
|
235
Docker/Docker资源限制.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# 资源限制
|
||||
默认情况下,容器没有资源限制,可以使用主机内核调度程序允许的尽可能多的给定资源,docker提供了控制容器可以限制容器使用多少内存或者cpu的方法,设置docker run命令的运行时配置标志。
|
||||
|
||||
其中一些功能要求宿主机的内核支持Linux功能,要检查支持,可以使用docker info命令,如果内核中禁用了某项功能,可能会在输出结尾处看到警告。
|
||||
|
||||
## cgroup介绍
|
||||
在一个容器内部,如果不对其做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如cpu、内存等,Linux Cgroups的全称是Linux control Groups,它最重要的作用就是限制一个进程组能够使用的资源上线,包括cpu、内存、磁盘、网络等等。
|
||||
|
||||
## 开启cgroup功能
|
||||
- 验证系统内核层已经默认开启cgroup功能
|
||||
```bash
|
||||
[root@docker-server ~]# cat /boot/config-3.10.0-957.el7.x86_64| grep cgroup -i
|
||||
CONFIG_CGROUPS=y
|
||||
# CONFIG_CGROUP_DEBUG is not set
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_PIDS=y
|
||||
CONFIG_CGROUP_DEVICE=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_CGROUP_HUGETLB=y
|
||||
CONFIG_CGROUP_PERF=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_BLK_CGROUP=y
|
||||
# CONFIG_DEBUG_BLK_CGROUP is not set
|
||||
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
|
||||
CONFIG_NET_CLS_CGROUP=y
|
||||
CONFIG_NETPRIO_CGROUP=y
|
||||
```
|
||||
|
||||
- 关于内存的模块
|
||||
```bash
|
||||
[root@docker-server ~]# cat /boot/config-3.10.0-957.el7.x86_64 | grep mem -i | grep cg -i
|
||||
CONFIG_MEMCG=y
|
||||
CONFIG_MEMCG_SWAP=y
|
||||
CONFIG_MEMCG_SWAP_ENABLED=y
|
||||
CONFIG_MEMCG_KMEM=y
|
||||
```
|
||||
|
||||
# 容器CPU限制
|
||||
一个宿主机,有几十个核心的cpu,但是宿主机上可以同时运行成百上千个不同的进程用以处理不同的任务,多进程共用一个cpu的核心依赖计数就是为可压缩资源,即一个核心cpu可以通过调度而运行多个进程,但是在同一个单位时间内只能由一个进程在cpu上运行,那么这么多的进程怎么在cpu上执行和调度的呢?(进程优先级)
|
||||
|
||||
默认情况下,每个容器对主机cpu周期的访问权限是不受限制的,但是我们可以人为干扰。
|
||||
|
||||
## 相关参数说明
|
||||
|
||||
| 参数名 | 默认值 | 说明 | 使用建议 |
|
||||
|--------|---------|------|----------|
|
||||
| --cpus | 无限制 | 指定容器可使用的CPU核心数量。例如设置为1.5表示容器最多可使用1.5个CPU核心的计算能力。 | • 推荐使用此参数控制CPU使用<br>• 设置范围建议为0.1-核心总数<br>• 生产环境必须设置 |
|
||||
| --cpu-period | 100000 | 设置CPU CFS调度周期(单位:微秒)。必须与--cpu-quota一起使用。 | • 不建议单独使用<br>• 建议使用--cpus替代<br>• 默认周期100ms适用大多数场景 |
|
||||
| --cpu-quota | -1 | 设置CPU CFS配额(单位:微秒)。与--cpu-period配合使用,quota/period的值等效于--cpus的值。 | • 不建议单独使用<br>• 建议使用--cpus替代<br>• 仅在需要精细调度时使用 |
|
||||
| --cpuset-cpus | 无限制 | 指定容器可以使用的CPU核心编号,如"0,2"表示只能使用0号和2号CPU核心。 | • 适用于CPU绑核场景<br>• 可提高缓存命中率<br>• 注意预留系统CPU资源 |
|
||||
| --cpuset-mems | 无限制 | 指定容器使用的NUMA节点。仅在NUMA架构服务器中有效。 | • 仅用于NUMA架构<br>• 需了解硬件架构再使用<br>• 一般场景不建议使用 |
|
||||
| --cpu-shares | 1024 | 设置CPU资源分配的权重值。在CPU竞争时,权重值越大获得更多CPU时间片。 | • 设置范围2-262144<br>• 仅在CPU竞争时有效<br>• 适合差异化CPU分配 |
|
||||
|
||||
> **最佳实践建议**:
|
||||
> 1. 生产环境建议使用--cpus参数限制CPU使用
|
||||
> 2. 按实际需求合理设置CPU限制,预留足够系统资源
|
||||
> 3. 特殊场景(如CPU密集型)可考虑使用cpuset-cpus绑核
|
||||
> 4. 避免过度限制导致容器性能问题
|
||||
|
||||
## 实践案例
|
||||
|
||||
### 案例1: CPU无限制
|
||||
|
||||
启动1个进程,占用4核cpu,未限制容器会把cpu全部占完
|
||||
|
||||
```bash
|
||||
# 查看我们宿主机的cup数量
|
||||
[root@localhost ~]# top
|
||||
top - 21:32:49 up 43 min, 2 users, load average: 3.54, 1.82, 0.80
|
||||
Tasks: 186 total, 1 running, 185 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.5 hi, 0.0 si, 0.0 st
|
||||
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
|
||||
[root@localhost ~]# docker run -it --rm --name test1 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 4 cpu, 1 vm
|
||||
|
||||
# 新建窗口查看
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
c6a795e4c09f test1 396.78% 282.6MiB / 1.703GiB 16.21% 876B / 126B 0B / 0B 7
|
||||
|
||||
# 可以看出CPU的使用率大概是400% 因为我们是4个核心,单个核心跑满是100%
|
||||
```
|
||||
|
||||
### 案例2: CPU限制
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it --rm --cpus 2 --name test1 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 4 cpu, 1 vm
|
||||
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
5b7dcb36d738 test1 200.65% 279.7MiB / 1.703GiB 16.04% 876B / 126B 0B / 0B 7
|
||||
|
||||
[root@localhost ~]# top
|
||||
top - 21:36:15 up 47 min, 3 users, load average: 1.38, 1.92, 1.05
|
||||
Tasks: 198 total, 8 running, 190 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu0 : 50.7 us, 1.4 sy, 0.0 ni, 47.2 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
%Cpu1 : 52.9 us, 0.0 sy, 0.0 ni, 47.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
%Cpu2 : 50.7 us, 0.0 sy, 0.0 ni, 48.6 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
%Cpu3 : 50.4 us, 0.0 sy, 0.0 ni, 48.9 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
|
||||
# 并且是平均使用所有的cup核心
|
||||
```
|
||||
|
||||
### 案例3: CPU绑定
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it --rm --cpus 2 --cpuset-cpus 0,2 --name test1 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
ee11d834dde5 test1 186.68% 1.488GiB / 1.781GiB 83.60% 648B / 0B 44.8GB / 95.7MB 25
|
||||
|
||||
[root@localhost ~]# top
|
||||
top - 21:38:25 up 49 min, 3 users, load average: 0.92, 1.40, 0.96
|
||||
Tasks: 197 total, 6 running, 191 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu0 : 97.3 us, 2.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
%Cpu1 : 0.3 us, 0.0 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
|
||||
%Cpu2 : 98.3 us, 1.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
%Cpu3 : 0.0 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st
|
||||
MiB Mem : 1743.4 total, 457.2 free, 924.2 used, 531.4 buff/cache
|
||||
MiB Swap: 2048.0 total, 2047.2 free, 0.8 used. 819.2 avail Mem
|
||||
```
|
||||
|
||||
- 基于cpu-shares对cpu进行切分
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it --rm -d --cpu-shares 1000 --name test1 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
[root@localhost ~]# docker run -it --rm -d --cpu-shares 500 --name test2 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
d6dd34edb722 test1 543.41% 819.6MiB / 1.781GiB 44.95% 648B / 0B 102MB / 154MB 13
|
||||
154b07a94e2f test2 241.15% 711.1MiB / 1.781GiB 39.00% 648B / 0B 406MB / 145MB
|
||||
```
|
||||
|
||||
|
||||
# 容器MEM限制
|
||||
## OOM异常
|
||||
对于Linux主机,如果没有足够的内存来执行其他重要的系统任务,将会抛出OOM异常(内存溢出、内存泄漏、内存异常),随后系统会开始杀死进程以释放内存,凡是运行在宿主机的进程都有可能被kill,包括dockerd和其他的应用程序,如果重要的系统进程被kill,会导致和该进程相关的服务全部宕机。
|
||||
|
||||
产生OOM异常时,Dockerd尝试通过调整docker守护程序上的OOM优先级来减轻这些风险,以便它比系统上的其他进程更不可能被杀死,但是容器的OOM优先级未调整时单个容器被杀死的可能性更大(不推荐调整容器的优先级这种方式)。
|
||||
|
||||
## OOM评分机制
|
||||
Linux会为每个进程计算一个分数,最终会将分数最高的进程kill掉。相关参数说明如下:
|
||||
|
||||
| 参数名 | 取值范围 | 说明 | 使用建议 |
|
||||
|--------|----------|------|----------|
|
||||
| oom_score_adj | -1000 到 1000 | 用于调整进程的OOM评分。值越高,进程在内存不足时越容易被kill。设置为-1000时进程永远不会被kernel kill。 | • 关键系统进程建议设置较低值<br>• 非关键应用可保持默认值<br>• 谨慎使用-1000,可能导致系统不稳定 |
|
||||
| oom_adj | -17 到 +15 | 旧版本参数,用于调整进程被kill的优先级。值越高越容易被kill,-17表示不能被kill。 | • 建议使用oom_score_adj替代<br>• 仅为了兼容旧版本内核<br>• 不推荐在新系统中使用 |
|
||||
| oom_score | 系统计算得出 | 系统根据进程的内存使用量、CPU时间、运行时长和oom_adj综合计算的得分。得分越高越容易被kill。 | • 用于监控进程的OOM风险<br>• 定期检查高内存占用进程<br>• 发现异常及时优化或限制 |
|
||||
|
||||
> **最佳实践建议**:
|
||||
> 1. 为关键进程适当降低OOM评分,避免被意外kill
|
||||
> 2. 定期监控高内存进程的oom_score
|
||||
> 3. 合理规划内存使用,避免触发OOM
|
||||
> 4. 使用容器时建议设置内存限制
|
||||
|
||||
## 相关参数说明
|
||||
|
||||
| 参数名 | 说明 | 默认值 | 使用建议 |
|
||||
|--------|------|--------|----------|
|
||||
| -m 或 --memory | 容器可使用的最大物理内存量 | 无限制 | • 最小值为4m<br>• 建议根据应用实际需求设置<br>• 生产环境必须设置 |
|
||||
| --memory-swap | 容器可使用的交换分区和物理内存总和 | -1 (不限制) | • 需要先设置-m参数<br>• 频繁交换会影响性能<br>• 建议生产环境禁用swap |
|
||||
| --memory-swappiness | 容器使用交换分区的倾向性 | 继承主机设置 | • 范围0-100<br>• 0表示尽量不使用swap<br>• 生产环境建议设为0 |
|
||||
| --kernel-memory | 容器可使用的最大内核内存量 | 无限制 | • 最小值为4m<br>• **不建议使用**<br>• 可能导致主机资源阻塞 |
|
||||
| --memory-reservation | 内存软限制(小于--memory) | 无限制 | • 系统内存紧张时激活<br>• 作为内存使用预警<br>• 建议设置为--memory的80% |
|
||||
| --oom-kill-disable | 禁止OOM时杀死容器进程 | false | • 仅在设置-m时有效<br>• 需谨慎使用<br>• 建议保持默认值 |
|
||||
|
||||
> **最佳实践建议**:
|
||||
> 1. 生产环境必须设置-m参数限制内存使用
|
||||
> 2. 建议禁用或限制swap使用
|
||||
> 3. 合理设置memory-reservation作为预警
|
||||
> 4. 谨慎使用kernel-memory和oom-kill-disable
|
||||
|
||||
## 实践案例
|
||||
如果一个容器未作内存使用限制,则该容器可以利用到系统内存最大空间,默认创建的容器没有做内存资源限制
|
||||
|
||||
### 案例1: MEM无限制
|
||||
- 拉取容器压测工具镜像
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker pull lorel/docker-stress-ng
|
||||
[root@docker-server1 ~]# docker run -it --rm lorel/docker-stress-ng -help
|
||||
```
|
||||
|
||||
- 使用压测工具开启两个工作进程,每个工作进程最大允许使用内存256M,且宿主机不限制当前容器的最大内存
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker run -it --rm --name test1 lorel/docker-stress-ng --vm 2 --vm-bytes 256m
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 2 vm
|
||||
|
||||
[root@docker-server1 ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
3ca32774fc20 test1 185.16% 514.3MiB / 1.781GiB 28.21% 648B / 0B 0B / 0B 5
|
||||
|
||||
```
|
||||
|
||||
### 案例2: MEM限制
|
||||
- 宿主机限制最大内存使用
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker run -it --rm -m 256m --name test2 lorel/docker-stress-ng --vm 2 --vm-bytes 256m
|
||||
[root@docker-server1 ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
bfff488e6185 test1 169.76% 255.8MiB / 256MiB 99.91% 648B / 0B 3.53GB / 10.6GB 5
|
||||
```
|
||||
|
||||
- 可以通过修改cgroup文件值来扩大内存限制,缩小会报错
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# cat /sys/fs/cgroup/memory/docker/bfff488e618580b227b5411c91b35517850e95af2ac2225b45180937c14e70c2/memory.limit_in_bytes
|
||||
```
|
||||
|
||||
**内存软限制**
|
||||
|
||||
软限制不会真正限制到内存的使用
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker run -it --rm -m 256m --memory-reservation 128m --name test1 lorel/docker-stress-ng --vm 2 --vm-bytes 256m
|
||||
[root@docker-server1 ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
0ffb4b8fdbde test1 174.52% 255.9MiB / 256MiB 99.95% 648B / 0B 5.33GB / 18.1GB 5
|
||||
```
|
||||
|
||||
**交换分区限制**
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker run -it --rm -m 256m --memory-swap 512m --name test1 lorel/docker-stress-ng --vm 2 --vm-bytes 256m
|
||||
```
|
81
Docker/Docker资源隔离.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Linux namespace技术
|
||||
如果一个宿主机运行了N个容器,多个容器带来的以下问题怎么解决:
|
||||
1. 怎么样保证每个容器都有不同的文件系统并且能互不影响?
|
||||
2. 一个docker主进程内的各个容器都是其子进程,那么如何实现同一个主进程下不同类型的子进程?各个子进程间通信能相互访问吗?
|
||||
3. 每个容器怎么解决IP以及端口分配的问题?
|
||||
4. 多个容器的主机名能一样吗?
|
||||
5. 每个容器都要不要有root用户?怎么解决账户重名问题呢?
|
||||
|
||||
**解决方案**:
|
||||
namespace 是 Linux 系统的底层概念,在内核层实现,即有一些不同类型的命名空间都部署在核内,各个容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各个docker容器运行在宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统、网络空间、进程空间等。
|
||||
|
||||
|
||||
| 隔离类型 | 功能说明 | 系统调用参数 | 内核版本 | 应用场景 |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| MNT Namespace(mount) | 提供磁盘挂载点和文件系统的隔离能力,使容器拥有独立的文件系统层次结构 | CLONE_NEWNS | 2.4.19 | 容器镜像管理、数据卷挂载、持久化存储 |
|
||||
| IPC Namespace(Inter-Process Communication) | 提供进程间通信的隔离能力,确保容器内进程通信安全 | CLONE_NEWIPC | 2.6.19 | 容器内消息队列、共享内存、信号量隔离 |
|
||||
| UTS Namespace(UNIX Timesharing System) | 提供主机名和域名的隔离能力,使容器拥有独立的主机标识 | CLONE_NEWUTS | 2.6.19 | 容器主机名管理、集群服务发现 |
|
||||
| PID Namespace(Process Identification) | 提供进程隔离能力,实现容器内进程树独立管理 | CLONE_NEWPID | 2.6.24 | 容器进程管理、应用程序运行时隔离 |
|
||||
| Net Namespace(network) | 提供网络栈的隔离能力,包括网络设备、IP地址、路由表等 | CLONE_NEWNET | 2.6.29 | 容器网络配置、跨主机通信、服务端口映射 |
|
||||
| User Namespace(user) | 提供用户和用户组的隔离能力,增强容器安全性 | CLONE_NEWUSER | 3.8 | 容器权限控制、用户映射、安全策略管理 |
|
||||
|
||||
# MNT Namespace
|
||||
提供磁盘挂载点和文件系统的隔离能力,使容器拥有独立的文件系统层次结构。
|
||||
```bash
|
||||
# 在容器内挂载 tmpfs 文件系统
|
||||
docker run -it --rm ubuntu bash
|
||||
mkdir /mnt/tmpfs
|
||||
mount -t tmpfs -o size=100M tmpfs /mnt/tmpfs
|
||||
# 宿主机上无法看到此挂载点
|
||||
df -h
|
||||
```
|
||||
|
||||
# IPC Namespace
|
||||
提供进程间通信的隔离能力,确保容器内进程通信安全。
|
||||
```shell
|
||||
# 容器A创建共享内存段
|
||||
docker run -it --name shm1 --rm ubuntu bash
|
||||
ipcmk -M 64M # 返回共享内存 ID(如 0)
|
||||
|
||||
# 容器B无法访问
|
||||
docker run -it --name shm2 --rm ubuntu bash
|
||||
ipcs -m
|
||||
```
|
||||
|
||||
# UTS Namespace
|
||||
提供主机名和域名的隔离能力,使容器拥有独立的主机标识。
|
||||
```shell
|
||||
# 启动容器并设置主机名
|
||||
docker run -it --hostname=myapp --rm ubuntu bash
|
||||
hostname
|
||||
```
|
||||
|
||||
# PID Namespace
|
||||
提供进程隔离能力,实现容器内进程树独立管理。
|
||||
```shell
|
||||
# 查看当前宿主机所有进程
|
||||
# 查看当前容器内所有进程
|
||||
```
|
||||
|
||||
**那么宿主机的PID与容器内的PID是什么关系?**
|
||||
1. **独立的 PID 命名空间**:
|
||||
- 每个 Docker 容器都有自己独立的 PID 命名空间。
|
||||
- 容器内的进程 PID 从 1 开始编号,与宿主机上的 PID 是相互独立的。
|
||||
2. **PID 映射**:
|
||||
- 容器内的进程 PID 与宿主机上的进程 PID 之间是有映射关系的。
|
||||
- 通过 `docker inspect <container_id>` 命令,可以查看容器内进程的 PID 与宿主机上进程 PID 的对应关系。
|
||||
3. **PID 可见性**:
|
||||
- 容器内的进程只能看到容器内部的 PID。
|
||||
- 宿主机上的进程可以看到容器内部的 PID,但容器内的进程无法看到宿主机上的 PID。
|
||||
4. **PID 隔离**:
|
||||
- 容器内的进程无法访问或影响宿主机上的其他进程。
|
||||
- 宿主机上的进程可以访问和管理容器内的进程。
|
||||
|
||||
# Net Namespace
|
||||
提供网络栈的隔离能力,包括网络设备、IP地址、路由表等。参考`08.Docker网络管理`
|
||||
|
||||
# User Namespace
|
||||
提供用户和用户组的隔离能力,增强容器安全性。
|
||||
```shell
|
||||
# A容器创建用户在B容器里不可见
|
||||
```
|
155
Docker/Docker镜像制作.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# 背景介绍
|
||||
Docker 镜像制作类似于虚拟机的模板制作,即按照公司的实际业务将需要安装的软件、相关配置等基础环境配置完成,然后将虚拟机再提交为模板,最后再批量从模板批量创建新的虚拟机,这样可以极大地简化业务中相同环境的虚拟机运行环境的部署工作,Docker的镜像制作分为手动制作可自动制作(基于 DockerFile ),企业通常都是基于 DockerFile 制作镜像。
|
||||
|
||||
# 手动制作nginx镜像
|
||||
```shell
|
||||
[root@docker-server ~]# docker run -it ubuntu bash
|
||||
root@1d8e32ab39d6:/# apt-get update & apt-get install nginx curl vim-tiny -y
|
||||
root@1d8e32ab39d6:/# echo 'eagleslab nginx' > /var/www/html/index.nginx-debian.html
|
||||
root@1d8e32ab39d6:/# grep daemon /etc/nginx/nginx.conf
|
||||
daemon off;
|
||||
|
||||
# 提交为镜像
|
||||
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
|
||||
[root@docker-server ~]# docker commit -a "v100" -m "my nginx image v1" 0195bc1d0f7b ubuntu_nginx:v1
|
||||
|
||||
# 通过ubuntu_nginx:v1镜像启动容器
|
||||
[root@docker-server ~]# docker run -d -p 8081:80 ubuntu_nginx:v1
|
||||
[root@docker-server ~]# curl 127.0.0.1:8081
|
||||
```
|
||||
**适用场景**:主要作用是将配置好的一些容器复用,再生成新的镜像。
|
||||
commit是合并了save、load、export、import这几个特性的一个综合性的命令,它主要做了:
|
||||
1. 将容器当前的读写层保存成一个新层。
|
||||
2. 和镜像的历史层一起合并成一个新的镜像
|
||||
3. 如果原本的镜像有3层,commit之后就会有4层,最新的一层为从镜像运行到commit之间对文件系统的修改。
|
||||
|
||||
# DockerFile制作镜像
|
||||
DockerFile可以说是一种可以被Docker程序解释的脚本,DockerFile是由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观地展示镜像是怎么产生的,有了写好的各种各样的DockerFIle文件,当后期某个镜像有额外的需求时,只要在之前的DockerFile添加或者修改相应的操作即可重新生成新的Docker镜像,避免了重复手动制作镜像的麻烦。
|
||||
|
||||
## 最佳实践
|
||||
```shell
|
||||
# Dockerfile
|
||||
## 使用官方 Ubuntu 22.04 LTS 作为基础镜像
|
||||
FROM ubuntu:22.04
|
||||
|
||||
## 设置环境变量避免交互式提示
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
## 安装 Nginx 并清理缓存(合并操作用于减少镜像层)
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
nginx \
|
||||
# 安装常用工具(可选)
|
||||
curl \
|
||||
vim-tiny && \
|
||||
# 清理APT缓存
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
## 删除默认配置文件(按需保留)
|
||||
RUN rm /etc/nginx/sites-enabled/default
|
||||
|
||||
## 暴露 HTTP 和 HTTPS 端口
|
||||
EXPOSE 80 443
|
||||
|
||||
## 创建日志目录(确保日志可持久化)
|
||||
RUN mkdir -p /var/log/nginx && \
|
||||
chown -R www-data:www-data /var/log/nginx
|
||||
|
||||
## 添加自定义配置(示例文件需存在于构建上下文)
|
||||
# COPY nginx.conf /etc/nginx/nginx.conf
|
||||
# COPY sites-available/ /etc/nginx/sites-available/
|
||||
|
||||
## 设置健康检查
|
||||
HEALTHCHECK --interval=30s --timeout=3s \
|
||||
CMD curl -f http://localhost/ || exit 1
|
||||
|
||||
## 以非root用户运行(Ubuntu官方nginx包已使用www-data用户)
|
||||
USER www-data
|
||||
|
||||
## 启动Nginx并保持前台运行
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
||||
# 通过Dockerfile构建镜像
|
||||
[root@docker-server ~]# docker build -t nginx:v1 .
|
||||
```
|
||||
## 优化说明
|
||||
- 层合并: 将多个`RUN`指令合并以减少镜像层数
|
||||
- 缓存清理: 清理APT缓存减小镜像体积
|
||||
- 安全实践: 非root用户运行;只读挂载配置文件
|
||||
- 可维护性: 显式声明暴露端口;健康检查配置;日志目录持久化
|
||||
- 稳定性: 指定精确的ubuntu版本;禁用Nginx后台模式
|
||||
|
||||
|
||||
## 指令说明
|
||||
操作指令
|
||||
|
||||
| 指令 | 说明 |
|
||||
| ------ | ---------------------------- |
|
||||
| `RUN` | 运行指定命令 |
|
||||
| `CMD` | 启动容器时指定默认执行的命令 |
|
||||
| `ADD` | 添加内容到镜像 |
|
||||
| `COPY` | 复制内容到镜像 |
|
||||
|
||||
配置指令
|
||||
|
||||
| 指令 | 说明 |
|
||||
| ------------- | ---------------------------------- |
|
||||
| `ARG` | 定义创建镜像过程中使用的变量 |
|
||||
| `FROM` | 指定所创建镜像的基础镜像 |
|
||||
| `LABEL` | 为生成的镜像添加元数据标签信息 |
|
||||
| `EXPOSE` | 声明镜像内服务监听的端口 |
|
||||
| `ENV` | 指定环境变量 |
|
||||
| `ENTRYPOINT` | 指定镜像的默认入口命令 |
|
||||
| `VOLUME` | 创建一个数据卷挂载点 |
|
||||
| `USER` | 指定运行容器时的用户名或UID |
|
||||
| `WORKDIR` | 配置工作目录 |
|
||||
| `ONBUILD` | 创建子镜像时指定自动执行的操作指令 |
|
||||
| `STOPSIGNAL` | 指定退出的信号值 |
|
||||
| `HEALTHCHECK` | 配置所启动容器如何进行健康检查 |
|
||||
| `SHELL` | 指定默认shell类型 |
|
||||
|
||||
|
||||
**注意事项**
|
||||
```shell
|
||||
# RUN
|
||||
- 运行指定命令
|
||||
- 每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像层
|
||||
- 当命令较长时可以使用\来换行
|
||||
|
||||
# CMD
|
||||
- 每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行
|
||||
- CMD指令用来指定启动容器时默认执行的命令,支持三种格式:
|
||||
CMD ["executable","param1","param2"]
|
||||
CMD command param1 param2`
|
||||
CMD ["param1","param2"]
|
||||
|
||||
# ADD
|
||||
- 该命令将复制指定的src路径下内容到容器中的dest路径下
|
||||
- src可以是DockerFIle所在目录的一个相对路径,也可以是一个url,还可以是一个tar
|
||||
- dest可以是镜像内绝对路径,或者相对于工作目录的相对路径
|
||||
|
||||
# COPY
|
||||
- COPY与ADD指令功能类似,当使用本地目录为源目录时,推荐使用COPY
|
||||
|
||||
# ARG
|
||||
- 定义创建过程中使用到的变量;比如:HTTP_PROXY 、HTTPS_PROXY 、FTP_PROXY 、NO_PROXY不区分大小写。
|
||||
|
||||
# FROM
|
||||
- 指定所创建镜像的基础镜像:为了保证镜像精简,可以选用体积较小的Alpin或Debian作为基础镜像
|
||||
|
||||
# EXPOSE
|
||||
- 声明镜像内服务监听的端口:该指令只是起到声明作用,并不会自动完成端口映射
|
||||
|
||||
# ENTRYPOINT
|
||||
- 指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数支持两种格式:
|
||||
ENTRYPOINT ["executable","param1","param2"]
|
||||
ENTRYPOINT command param1 param2
|
||||
- 此时CMD指令指定值将作为根命令的参数
|
||||
- 每个DockerFile中只能有一个ENTRYPOINT,当指定多个时只有最后一个起效
|
||||
|
||||
# VOLUME: 创建一个数据卷挂载点
|
||||
|
||||
# WORKDIR
|
||||
- 为后续的RUN、CMD、ENTRYPOINT指令配置工作目录:建议使用绝对路径
|
||||
```
|
118
Docker/Docker镜像管理.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# 镜像
|
||||
容器是一个独立的进程,它从哪里获取文件和配置?如何共享这些环境?
|
||||
|
||||
镜像是一个标准化包,其中包含运行容器所需的所有文件、二进制文件、库和配置。
|
||||
- MySQL 镜像会打包数据库二进制文件、配置文件和其他依赖项。
|
||||
- Python Web 应用镜像会打包 Python 运行时、应用代码及其所有依赖项。
|
||||
|
||||
镜像两个重要原则:
|
||||
1. 镜像是不可变的。一旦创建,就无法修改。只能创建新镜像或在其上进行更改。
|
||||
2. 镜像由层组成。每一层代表一组文件系统变更,包括添加、删除或修改文件。
|
||||
|
||||
|
||||
# 镜像管理
|
||||
## 搜索镜像
|
||||
`Usage: docker search [OPTIONS] TERM`
|
||||
```bash
|
||||
# 搜索包含关键字的镜像
|
||||
[root@docker-server ~]# docker search centos
|
||||
```
|
||||
可以看到返回了很多包含关键字的镜像,其中包括镜像名字、描述、点赞数(表示该镜像的受欢迎程度)、是否官方创建、是否自动创建。默认输出结果按照星级评价进行排序。
|
||||
|
||||

|
||||
|
||||
|
||||
## 下载镜像
|
||||
`Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST]`
|
||||
```bash
|
||||
# 下载nginx、centos、hello-world镜像
|
||||
[root@docker-server ~]# docker pull nginx
|
||||
[root@docker-server ~]# docker pull centos
|
||||
[root@docker-server ~]# docker pull hello-world
|
||||
```
|
||||
其中,NAME是镜像名称,TAG是镜像的标签(往往用来是表示版本信息),通常情况下,描述一个镜像需要包括名称+标签,如果不指定标签,标签的值默认为latest。
|
||||
|
||||
|
||||
## 镜像列表
|
||||
`Usage: docker image COMMAND`
|
||||
```bash
|
||||
# 列出本地所有镜像
|
||||
[root@docker-server ~]# docker image ls
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx latest d1a364dc548d 2 weeks ago 133MB
|
||||
...
|
||||
|
||||
# 字段说明
|
||||
- REPOSITORY:镜像仓库名称
|
||||
- TAG:镜像的标签信息
|
||||
- 镜像ID:唯一用来标识镜像,如果两个镜像的ID相同,说明他们实际上指向了同一个镜像,只是具有不同标签名称而已
|
||||
- CREATED:创建时间,说明镜像的最后更新时间
|
||||
- SIZE:镜像大小,优秀的镜像往往体积都较小
|
||||
```
|
||||
|
||||
|
||||
## 镜像标签
|
||||
`Usage: docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]`
|
||||
```bash
|
||||
[root@docker-server ~]# docker tag centos:latest mycentos:latest
|
||||
[root@docker-server ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx latest d1a364dc548d 2 weeks ago 133MB
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
## 镜像信息
|
||||
`Usage: docker image inspect [OPTIONS] IMAGE [IMAGE...]`
|
||||
```bash
|
||||
[root@docker-server ~]# docker inspect centos:latest
|
||||
[
|
||||
{
|
||||
"Id": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
|
||||
"RepoTags": [
|
||||
"centos:latest",
|
||||
"mycentos:latest"
|
||||
]
|
||||
...
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## 镜像创建信息
|
||||
`Usage: docker image history [OPTIONS] IMAGE`
|
||||
```bash
|
||||
[root@docker-server ~]# docker history centos:latest
|
||||
IMAGE CREATED CREATED BY SIZE COMMENT
|
||||
300e315adb2f 6 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
|
||||
...
|
||||
```
|
||||
|
||||
## 镜像导出
|
||||
`Usage: docker image save [OPTIONS] IMAGE [IMAGE...]`
|
||||
```bash
|
||||
[root@docker-server ~]# docker image save centos:latest -o /opt/centos.tar.gz
|
||||
[root@docker-server ~]# ll /opt/centos.tar.gz
|
||||
-rw------- 1 root root 216535040 6月 9 10:33 /opt/centos.tar.gz
|
||||
[root@docker-server ~]# docker image save centos:latest > /opt/centos-1.tar.gz
|
||||
[root@docker-server ~]# ll /opt/centos-1.tar.gz
|
||||
-rw-r--r-- 1 root root 216535040 6月 9 10:35 /opt/centos-1.tar.gz
|
||||
```
|
||||
|
||||
## 镜像导入
|
||||
`Usage: docker image load [OPTIONS]`
|
||||
```bash
|
||||
[root@docker-server ~]# docker image load -i /opt/centos.tar.gz
|
||||
Loaded image: centos:latest
|
||||
[root@docker-server ~]# docker image load < /opt/centos.tar.gz
|
||||
Loaded image: centos:latest
|
||||
```
|
||||
|
||||
## 删除镜像
|
||||
`Usage: docker image rm [OPTIONS] IMAGE [IMAGE...]`
|
||||
```bash
|
||||
[root@docker-server ~]# docker image rm nginx:latest
|
||||
Untagged: nginx:latest
|
||||
Untagged: nginx@sha256:6d75c99af15565a301e48297fa2d121e15d80ad526f8369c526324f0f7ccb750
|
||||
[root@docker-server ~]# docker image rm 300e315adb2f
|
||||
...
|
||||
```
|
BIN
Docker/docker介绍与安装/docker架构图.png
Normal file
After Width: | Height: | Size: 668 KiB |
BIN
Docker/docker介绍与安装/docker网络隔离.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
Docker/docker介绍与安装/容器与虚拟机对比.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
Docker/docker网络管理/Bridge网络类型.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
Docker/docker网络管理/Container网络类型.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
Docker/docker网络管理/Host网络类型.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
Docker/docker网络管理/None网络类型.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
Docker/docker镜像管理/docker_hub搜索.png
Normal file
After Width: | Height: | Size: 66 KiB |
1025
KVM虚拟化/KVM虚拟化技术.md
Normal file
BIN
KVM虚拟化/KVM虚拟化技术/21294643-bcd8f8a5a221c0a4.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/NAT网络拓扑.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20210813094307159.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817210521151.png
Normal file
After Width: | Height: | Size: 386 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817210947370.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817211201455.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817211255101.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817211335661.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817211437115.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817211521569.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817211602825.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817211733692.png
Normal file
After Width: | Height: | Size: 154 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817214618130.png
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/image-20240817214704100.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/timg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/u=3141761520,730594136&fm=26&gp=0.jpg
Normal file
After Width: | Height: | Size: 138 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/桥接网络拓扑.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
KVM虚拟化/KVM虚拟化技术/隔离网络拓扑.png
Normal file
After Width: | Height: | Size: 26 KiB |
131
Kubernetes/DashBoard.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# DashBoard
|
||||
|
||||
之前在kubernetes中完成的所有操作都是通过命令行工具kubectl完成的。其实,为了提供更丰富的用户体验,kubernetes还开发了一个基于web的用户界面(Dashboard)。用户可以使用Dashboard部署容器化的应用,还可以监控应用的状态,执行故障排查以及管理kubernetes中各种资源。
|
||||
|
||||
## 部署Dashboard
|
||||
|
||||
1) 下载yaml,并运行Dashboard
|
||||
|
||||
```shell
|
||||
# 下载yaml
|
||||
[root@k8s-master01 ~]# wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml
|
||||
|
||||
# 修改kubernetes-dashboard的Service类型
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: kubernetes-dashboard
|
||||
name: kubernetes-dashboard
|
||||
namespace: kubernetes-dashboard
|
||||
spec:
|
||||
type: NodePort # 新增
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 8443
|
||||
nodePort: 30009 # 新增
|
||||
selector:
|
||||
k8s-app: kubernetes-dashboard
|
||||
|
||||
# 部署
|
||||
[root@k8s-master01 ~]# kubectl create -f recommended.yaml
|
||||
|
||||
# 查看namespace下的kubernetes-dashboard下的资源
|
||||
[root@k8s-master01 ~]# kubectl get pod,svc -n kubernetes-dashboard
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/dashboard-metrics-scraper-c79c65bb7-zwfvw 1/1 Running 0 111s
|
||||
pod/kubernetes-dashboard-56484d4c5-z95z5 1/1 Running 0 111s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/dashboard-metrics-scraper ClusterIP 10.96.89.218 <none> 8000/TCP 111s
|
||||
service/kubernetes-dashboard NodePort 10.104.178.171 <none> 443:30009/TCP 111s
|
||||
```
|
||||
|
||||
2)创建访问账户,获取token
|
||||
|
||||
```shell
|
||||
# 创建账号
|
||||
[root@k8s-master01-1 ~]# kubectl create serviceaccount dashboard-admin -n kubernetes-dashboard
|
||||
|
||||
# 授权
|
||||
[root@k8s-master01-1 ~]# kubectl create clusterrolebinding dashboard-admin-rb --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin
|
||||
|
||||
# 获取账号token
|
||||
[root@k8s-master01 ~]# kubectl get secrets -n kubernetes-dashboard | grep dashboard-admin
|
||||
dashboard-admin-token-xbqhh kubernetes.io/service-account-token 3 2m35s
|
||||
|
||||
[root@k8s-master01 ~]# kubectl describe secrets dashboard-admin-token-xbqhh -n kubernetes-dashboard
|
||||
Name: dashboard-admin-token-xbqhh
|
||||
Namespace: kubernetes-dashboard
|
||||
Labels: <none>
|
||||
Annotations: kubernetes.io/service-account.name: dashboard-admin
|
||||
kubernetes.io/service-account.uid: 95d84d80-be7a-4d10-a2e0-68f90222d039
|
||||
|
||||
Type: kubernetes.io/service-account-token
|
||||
|
||||
Data
|
||||
====
|
||||
namespace: 20 bytes
|
||||
token: eyJhbGciOiJSUzI1NiIsImtpZCI6ImJrYkF4bW5XcDhWcmNGUGJtek5NODFuSXl1aWptMmU2M3o4LTY5a2FKS2cifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4teGJxaGgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiOTVkODRkODAtYmU3YS00ZDEwLWEyZTAtNjhmOTAyMjJkMDM5Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmVybmV0ZXMtZGFzaGJvYXJkOmRhc2hib2FyZC1hZG1pbiJ9.NAl7e8ZfWWdDoPxkqzJzTB46sK9E8iuJYnUI9vnBaY3Jts7T1g1msjsBnbxzQSYgAG--cV0WYxjndzJY_UWCwaGPrQrt_GunxmOK9AUnzURqm55GR2RXIZtjsWVP2EBatsDgHRmuUbQvTFOvdJB4x3nXcYLN2opAaMqg3rnU2rr-A8zCrIuX_eca12wIp_QiuP3SF-tzpdLpsyRfegTJZl6YnSGyaVkC9id-cxZRb307qdCfXPfCHR_2rt5FVfxARgg_C0e3eFHaaYQO7CitxsnIoIXpOFNAR8aUrmopJyODQIPqBWUehb7FhlU1DCduHnIIXVC_UICZ-MKYewBDLw
|
||||
ca.crt: 1025 bytes
|
||||
```
|
||||
|
||||
3)通过浏览器访问Dashboard的UI
|
||||
|
||||
在登录页面上输入上面的token
|
||||
|
||||

|
||||
|
||||
出现下面的页面代表成功
|
||||
|
||||

|
||||
|
||||
## 使用DashBoard
|
||||
|
||||
本章节以Deployment为例演示DashBoard的使用
|
||||
|
||||
**查看**
|
||||
|
||||
选择指定的命名空间`dev`,然后点击`Deployments`,查看dev空间下的所有deployment
|
||||
|
||||

|
||||
|
||||
**扩缩容**
|
||||
|
||||
在`Deployment`上点击`规模`,然后指定`目标副本数量`,点击确定
|
||||
|
||||

|
||||
|
||||
**编辑**
|
||||
|
||||
在`Deployment`上点击`编辑`,然后修改`yaml文件`,点击确定
|
||||
|
||||

|
||||
|
||||
**查看Pod**
|
||||
|
||||
点击`Pods`, 查看pods列表
|
||||
|
||||

|
||||
|
||||
**操作Pod**
|
||||
|
||||
选中某个Pod,可以对其执行日志(logs)、进入执行(exec)、编辑、删除操作
|
||||
|
||||

|
||||
|
||||
> Dashboard提供了kubectl的绝大部分功能,这里不再一一演示
|
||||
|
||||
# kuboard
|
||||
|
||||
## 特点介绍
|
||||
|
||||
相较于 Kubernetes Dashboard 等其他 Kubernetes 管理界面,Kuboard 的优势更加明显,官方网站:https://kuboard.cn/
|
||||
|
||||
## 安装教程
|
||||
|
||||
https://kuboard.cn/v4/install/quickstart.html
|
||||
|
||||
安装好后链接上集群,最终界面如下
|
||||
|
||||

|
BIN
Kubernetes/DashBoard/image-20200520144548997.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
Kubernetes/DashBoard/image-20200520144959353.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
Kubernetes/DashBoard/image-20200520154628679.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
Kubernetes/DashBoard/image-20200520162605102.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
Kubernetes/DashBoard/image-20200520163253644.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
Kubernetes/DashBoard/image-20200520163552110.png
Normal file
After Width: | Height: | Size: 107 KiB |
BIN
Kubernetes/DashBoard/image-20200520163832827.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
Kubernetes/DashBoard/image-20240918150900081.png
Normal file
After Width: | Height: | Size: 191 KiB |
5
Kubernetes/Kubernetes.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Kubernetes 是一个开源的容器编排引擎,用于自动化部署、扩展和管理容器化应用程序。该开源项目由云原生计算基金会(CNCF)托管。
|
||||
|
||||
[kubernetes官网地址](https://kubernetes.io/)
|
||||
|
||||
[kubernetes项目地址](https://github.com/kubernetes)
|
166
Kubernetes/Kubernetes概述.md
Normal file
@@ -0,0 +1,166 @@
|
||||
# 云计算的三种模式
|
||||
|
||||
## 单机到云原生的演变
|
||||
|
||||

|
||||
|
||||
## IAAS
|
||||
|
||||
Infrastructure as a Service 基础设施即服务
|
||||
|
||||

|
||||
|
||||
## PAAS
|
||||
|
||||
Platform as a service 平台即服务
|
||||
|
||||

|
||||
|
||||
## SAAS
|
||||
|
||||
Software as a Service
|
||||
|
||||
# 容器编排工具
|
||||
|
||||
## Borg
|
||||
|
||||
Borg 是 Google 早期开发的集群管理系统,用于管理大规模的容器化⼯作负载。它是 Google 内部的⼀个关键基础设施,自 2003 年开始使用。
|
||||
|
||||
## Omega
|
||||
|
||||
Omega 是 Borg 的⼀个后继系统,于 2013 年开始开发,旨在解决 Borg 在大规模、动态、多租户环境下多租户、声明式配置。
|
||||
|
||||
## kubernetes
|
||||
|
||||
Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。kubernetes 拥有一个庞大且快速增长的生态系统。kubernetes 的服务、支持和工具广泛可用。
|
||||
|
||||
kubernetes 这个名字源于希腊于,意为舵手或飞行员。k8s 这个缩写是因为k和s之间有八个字符的关系。google 在 2014 年开源了 kubernetes 项目。kubernetes建立在 google 在大规模运行生产工作负载方面拥有十几年的经验的基础上,结合了社区中最好的想法和实践。
|
||||
|
||||
# kubernetes优势
|
||||
|
||||
- 服务发现和负载均衡
|
||||
- 存储编排(添加任何本地或云服务器)
|
||||
- 自动部署和回滚
|
||||
|
||||
- 自动分配 CPU/内存资源
|
||||
- 弹性伸缩
|
||||
- 自我修复(需要时启动新容器)
|
||||
- Secret(安全相关信息)和配置管理
|
||||
- 大型规模的支持
|
||||
- 每个节点的Pod数量不超过 110
|
||||
- 节点数不超过 5000
|
||||
- Pod总数不超过 150000
|
||||
- 容器总数不超过 300000
|
||||
- 开源
|
||||
|
||||

|
||||
|
||||
## kubernetes现状
|
||||
|
||||

|
||||
|
||||
# kubernetes组件
|
||||
|
||||

|
||||
|
||||
一个kubernetes集群由一组被称作节点的机器组成。这些节点上运行Kubernetes所管理的容器化应用。集群具有至少一个工作节点。
|
||||
|
||||
工作节点会托管Pod,而Pod就是作为应用负载的组件。控制平面管理集群中的工作节点和Pod。在生产环境中,控制平面通常跨多台计算机运行,一个集群通常运行多个节点,提供容错性和高可用性。
|
||||
|
||||
## 控制平面组件(Control Plane Components)
|
||||
|
||||
控制平面组件会为集群做出全局决策,比如资源的调度。以及检测和响应集群事件,例如当不满足部署的 `replicas`字段时,要启动新的Pod)。
|
||||
|
||||
控制平面组件可以在集群中的任何节点上运行。然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件,并且不会在此计算机上运行用户容器。
|
||||
|
||||
### kube-apiserver
|
||||
|
||||
`kube-apiserver`负责公开Kubernetes API,处理接受请求的工作,是控制平面的前端。
|
||||
|
||||
`kube-apiserver`设计上考虑了水平扩缩,所以可通过部署多个实例来进行扩缩,并在这些实例之间平衡流量。
|
||||
|
||||
### etcd
|
||||
|
||||
一致且高可用的键值存储,用作Kubernetes所有集群数据的后台数据库。
|
||||
|
||||
### kube-scheduler
|
||||
|
||||
`kube-scheduler`负责监视新创建的、未指定运行节点(node)的Pods,并选择节点来让Pod在上面运行。
|
||||
|
||||
调度决策考虑的因素包括单个Pod及Pods集合的资源需求、软硬件及策略约束、亲和性及反亲和性规范、数据位置、工作负载间的干扰及最后时限。
|
||||
|
||||
### kube-controller-manager
|
||||
|
||||
`kube-controller-manager`负责运行控制器进程,控制器通过 API 服务器监控集群的公共状态,并致力于将当前状态转变为期待状态。
|
||||
|
||||
不同类型的控制器如下:
|
||||
- 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应。
|
||||
- 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pod 来运行这些任务直至完成。
|
||||
- 端点分片控制器(EndpointSlice controller):填充端点分片(EndpointSlice)对象(以提供 Service 和 Pod 之间的链接)。
|
||||
- 服务账号控制器(ServiceAccount controller):为新的命名空间创建默认的服务账号(ServiceAccount)。
|
||||
- ...
|
||||
|
||||
## Node组件
|
||||
|
||||
节点组件会在每个节点上运行,负责维护运行的 Pod 并提供 Kubernetes 运行环境。
|
||||
|
||||
### kubelet
|
||||
|
||||
`kubelet`会在集群中每个节点(node)上运行。它保证容器(containers)都运行在Pod中。
|
||||
|
||||
`kubelet`接收一组通过各类机制提供给它的PodSpec,确保这些 PodSpec 中描述的容器处于运行状态且健康。kubelet不会管理不是由 Kubernetes创建的容器。
|
||||
|
||||
### kube-proxy
|
||||
|
||||
kube-proxy 是集群中每个节点(node)上所运行的网络代理, 实现 Kubernetes 服务(Service) 概念的一部分。
|
||||
|
||||
kube-proxy 维护节点上的一些网络规则, 这些网络规则会允许从集群内部或外部的网络会话与 Pod 进行网络通信。
|
||||
|
||||
如果操作系统提供了可用的数据包过滤层,则 kube-proxy 会通过它来实现网络规则。 否则,kube-proxy 仅做流量转发。
|
||||
|
||||
### 容器运行时(Container Runtime)
|
||||
|
||||
这个基础组件使Kubernetes能够有效运行容器。 它负责管理 Kubernetes 环境中容器的执行和生命周期。
|
||||
|
||||
Kubernetes支持许多容器运行环境,例如 containerd、 CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他任何实现。
|
||||
|
||||
|
||||
## 插件(Addons)
|
||||
|
||||
插件使用Kubernetes资源(DaemonSet、Deployment等)实现集群功能。因为这些插件提供集群级别的功能,插件中命名空间域的资源属于`kube-system`命名空间。
|
||||
|
||||
### DNS
|
||||
|
||||
尽管其他插件都并非严格意义上的必需组件,但几乎所有 Kubernetes 集群都应该有集群 DNS,因为很多示例都需要 DNS 服务。
|
||||
|
||||
集群DNS是多个 DNS 服务器一起工作,为 Kubernetes 服务提供 DNS 记录。
|
||||
|
||||
Kubernetes 启动的容器会自动将这些 DNS 服务器配置其 DNS 搜索列表中。
|
||||
|
||||
### Web 界面(仪表盘)
|
||||
|
||||
Dashboard 是 Kubernetes 集群的通用的、基于 Web 的用户界面。 它使用户可以管理集群中运行的应用程序以及集群本身, 并进行故障排。
|
||||
|
||||
### 容器资源监控
|
||||
|
||||
容器资源监控 将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中, 并提供浏览这些数据的界面。
|
||||
|
||||
### 集群层面日志
|
||||
|
||||
集群层面日志机制负责将容器的日志数据保存到一个集中的日志存储中, 这种集中日志存储提供搜索和浏览接口。
|
||||
|
||||
### 网络插件
|
||||
|
||||
网络插件是实现容器网络接口(CNI)规范的软件组件。它们负责为 Pod 分配 IP 地址,并使这些 Pod 能在集群内部相互通信。
|
||||
|
||||
|
||||
# 扩展阅读
|
||||
[Kubernetes CRI (容器运行环境接口)](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/container-runtime-interface.md)
|
||||
|
||||
[网络插件](https://v1-29.docs.kubernetes.io/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
|
||||
|
||||
[集群网络](https://v1-29.docs.kubernetes.io/zh-cn/docs/concepts/cluster-administration/addons/#networking-and-network-policy)
|
||||
|
||||
[控制器列表]()
|
||||
|
||||
[ETCD](https://etcd.io/docs/)
|
310
Kubernetes/Pod与网络.md
Normal file
@@ -0,0 +1,310 @@
|
||||
# pod概念
|
||||
|
||||
<img src="pod与网络/image-20240904112128424.png" alt="image-20240904112128424" style="zoom:33%;" />
|
||||
|
||||
首先我们要明确一个概念,Kubernetes并不是只支持Docker这一个容器运行时,Kubernetes通过CRI这个抽象层,支持除Docker之外的其他容器运行时,比如rkt甚至支持客户自定义容器运行时。
|
||||
|
||||
- 第一个原因:借助CRI这个抽象层,使得Kubernetes不依赖于底层某一种具体的容器运行时实现技术,而是直接操作pod,pod内部再管理多个业务上紧密相关的用户业务容器,这种架构便于Kubernetes做扩展。
|
||||
- 第二个原因,我们假设Kubernetes没有pod的概念,而是直接管理容器,那么一组容器作为一个单元,假设其中一个容器死亡了,此时这个单元的状态应该如何定义呢?应该理解成整体死亡,还是个别死亡?
|
||||
|
||||
这个问题不易回答的原因,是因为包含了这一组业务容器的逻辑单元,没有一个统一的办法来代表整个容器组的状态,这就是Kubernetes引入pod的概念,并且每个pod里都有一个Kubernetes系统自带的pause容器的原因,通过引入pause这个与业务无关并且作用类似于Linux操作系统守护进程的Kubernetes系统标准容器,以pause容器的状态来代表整个容器组的状态。
|
||||
|
||||
<img src="pod与网络/image-20240904112421964.png" alt="image-20240904112421964" style="zoom: 33%;" />
|
||||
|
||||
- 第三个原因:pod里所有的业务容器共享pause容器的IP地址,以及pause容器mount的Volume,通过这种设计,业务容器之间可以直接通信,文件也能够直接彼此共享。
|
||||
|
||||
## Pause特性
|
||||
|
||||
- Pod内部第一个启动的容器
|
||||
- 初始化网络栈
|
||||
- 挂载需要的存储卷
|
||||
- 回收僵⼫进程
|
||||
- 容器与Pause容器共享名字空间(Network、PID、IPC)
|
||||
|
||||
# 实战:基于Docker模拟pod
|
||||
|
||||
- 编写Nginx配置文件
|
||||
|
||||
```bash
|
||||
cat <<EOF>> nginx.conf
|
||||
error_log stderr;
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
http {
|
||||
access_log /dev/stdout combined;
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name example.com www.example.com;
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:2368;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
- 启动容器
|
||||
|
||||
```bash
|
||||
docker run --name pause -p 8080:80 -d k8s.gcr.io/pause:3.1
|
||||
|
||||
docker run --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf --net=container:pause --ipc=container:pause --pid=container:pause -d nginx
|
||||
|
||||
docker run -d --name ghost -e NODE_ENV=development --net=container:pause --ipc=container:pause --pid=container:pause ghost
|
||||
```
|
||||
|
||||

|
||||
|
||||
# kubernetes网络
|
||||
|
||||
## 基本概述
|
||||
|
||||
Kubernetes的网络模型假定了所有Pod都在一个可以直接连通的扁平的网络空间中,这在GCE(Google Compute Engine)里面是现成的网络模型,Kubernetes假定这个网络已经存在。而在私有云里搭建Kubernetes集群,就不能假定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的Docker容器之间的互相访问先打通,然后运行Kubernetes。
|
||||
|
||||
## 网络模型原则
|
||||
|
||||
- 在不使用网络地址转换(NAT)的情况下,集群中的Pod能够与任意其他Pod进行通信
|
||||
- 在不使用网络地址转换(NAT)的情况下,在集群节点上运行的程序能与同一节点上的任何Pod进行通信
|
||||
- 每个Pod都有自己的IP地址(IP-per-Pod),并且任意其他Pod都可以通过相同的这个地址访问它
|
||||
|
||||
## CNI
|
||||
|
||||
借助CNI标准,Kubernetes可以实现容器网络问题的解决。通过插件化的方式来集成各种网络插件,实现集群内部网络相互通信,只要实现CNI标准中定义的核心接口操作(ADD,将容器添加到网络;DEL,从网络中删除一个容器;CHECK,检查容器的网络是否符合预期等)。CNI插件通常聚焦在容器到容器的网络通信。
|
||||
|
||||

|
||||
|
||||
CNI的接口并不是指HTTP,gRPC这种接口,CNI接口是指对可执行程序的调用(exec)可执行程序,Kubernetes节点默认的CNI插件路径为/opt/cni/bin
|
||||
|
||||
```bash
|
||||
[root@master01 ~]# ls /opt/cni/bin/
|
||||
bandwidth calico dhcp firewall host-device install loopback portmap sbr tap vlan
|
||||
bridge calico-ipam dummy flannel host-local ipvlan macvlan ptp static tuning vrf
|
||||
```
|
||||
|
||||
CNI通过JSON格式的配置文件来描述网络配置,当需要设置容器网络时,由容器运行时负责执行CNI插件,并通过CNI插件的标准输入(stdin)来传递配置文件信息,通过标准输出(stdout)接收插件的执行结果。从网络插件功能可以分为五类:
|
||||
|
||||

|
||||
|
||||
- **Main插件**
|
||||
- 创建具体网络设备
|
||||
- bridge:网桥设备,连接container和host;
|
||||
- ipvlan:为容器增加ipvlan网卡;
|
||||
- loopback:IO设备;
|
||||
- macvlan:为容器创建一个MAC地址;
|
||||
- ptp:创建一对Veth Pair;
|
||||
- vlan:分配一个vlan设备;
|
||||
- host-device:将已存在的设备移入容器内
|
||||
- **IPAM插件**:
|
||||
- 负责分配IP地址
|
||||
- dhcp:容器向DHCP服务器发起请求,给Pod发放或回收IP地址;
|
||||
- host-local:使用预先配置的IP地址段来进行分配;
|
||||
- static:为容器分配一个静态IPv4/IPv6地址,主要用于debug
|
||||
- **META插件**:
|
||||
- 其他功能的插件
|
||||
- tuning:通过sysctl调整网络设备参数;
|
||||
- portmap:通过iptables配置端口映射;
|
||||
- bandwidth:使用TokenBucketFilter来限流;
|
||||
- sbr:为网卡设置source based routing;
|
||||
- firewall:通过iptables给容器网络的进出流量进行限制
|
||||
- **Windows插件**:专门用于Windows平台的CNI插件(win-bridge与win-overlay网络插件)
|
||||
- **第三方网络插件**:第三方开源的网络插件众多,每个组件都有各自的优点及适应的场景,难以形成统一的标准组件,常用有Flannel、Calico、Cilium、OVN网络插件
|
||||
|
||||

|
||||
|
||||
## 网络插件
|
||||
|
||||
<img src="pod与网络/image-20240904135815763.png" alt="image-20240904135815763" style="zoom:33%;" />
|
||||
|
||||
### 人气数据
|
||||
|
||||
数据更新时间:2024-09-04
|
||||
|
||||
| 提供商 | 项目 | Stars | Forks | Contributors |
|
||||
| ------- | --------------------------------------- | ----- | ----- | ------------ |
|
||||
| Canal | https://github.com/projectcalico/canal | 714 | 100 | 20 |
|
||||
| Flannel | https://github.com/flannel-io/flannel | 8.7k | 2.9k | 235 |
|
||||
| Calico | https://github.com/projectcalico/calico | 5.9k | 1.3k | 353 |
|
||||
| Weave | https://github.com/weaveworks/weave/ | 6.6k | 668 | 87 |
|
||||
| Cilium | https://github.com/cilium/cilium | 19.7k | 2.9k | 803 |
|
||||
|
||||
功能说明
|
||||
|
||||
| 提供商 | 网络模型 | 路由分发 | 网络策略 | 网格 | 外部数据存储 | 加密 | Ingress/Egress策略 |
|
||||
| ------- | ------------------------ | -------- | -------- | ---- | -------------- | ---- | ------------------ |
|
||||
| Canal | 封装(VXLAN) | 否 | 是 | 否 | K8s API | 是 | 是 |
|
||||
| Flannel | 封装(VXLAN) | 否 | 否 | 否 | K8s API | 是 | 中 |
|
||||
| Calico | 封装(VXLAN,IPIP),未封装 | 是 | 是 | 是 | Etcd 和K8s API | 是 | 是 |
|
||||
| Weave | 封装 | 是 | 是 | 是 | 否 | 是 | 是 |
|
||||
| Cilium | 封装(VXLAN) | 是 | 是 | 是 | Etcd和K8sAPI | 是 | 是 |
|
||||
|
||||
- 网络模型:封装或未封装。
|
||||
- 路由分发:一种外部网关协议,用于在互联网上交换路由和可达性信息。BGP可以帮助进行跨集群pod之间的网络。此功能对于未封装的CNI网络插件是必须的,并且通常由BGP完成。如果你想构建跨网段拆分的集群,路由分发是一个很好的功能。
|
||||
- 网络策略:Kubernetes提供了强制执行规则的功能,这些规则决定了哪些service可以使用网络策略进行相互通信。这是从Kubernetes1.7起稳定的功能,可以与某些网络插件一起使用。
|
||||
- 网格:允许在不同的Kubernetes集群间进行service之间的网络通信。
|
||||
- 外部数据存储:具有此功能的CNI网络插件需要一个外部数据存储来存储数据。
|
||||
- 加密:允许加密和安全的网络控制和数据平面。
|
||||
- Ingress/Egress策略:允许你管理Kubernetes和非Kubernetes通信的路由控制。
|
||||
|
||||
## 网络模型
|
||||
|
||||
- underlay network(非封装网络)
|
||||
- 现实的物理基础层网络设备
|
||||
- underlay就是数据中心场景的基础物理设施,保证任何两个点路由可达,其中包含了传统的网络技术
|
||||
- overlay network(封装网络)
|
||||
- 一个基于物理网络之上构建的逻辑网络
|
||||
- overlay是在网络技术领域指的是一种网络架构上叠加的虚拟化技术模式
|
||||
- Overlay网络技术多种多样,一般采用TRILL、VxLan、GRE、NVGRE等隧道技术
|
||||
|
||||
### overlay
|
||||
|
||||

|
||||
|
||||
### underlay
|
||||
|
||||

|
||||
|
||||
## calico
|
||||
|
||||
或许是目前最主流的网络解决方案-calico
|
||||
|
||||
Calico是一个纯三层的虚拟网络,它没有复用docker的docker0网桥,而是自己实现的,calico网络不对数据包进行额外封装,不需要NAT和端口映射
|
||||
|
||||
### calico架构
|
||||
|
||||
<img src="pod与网络/image-20240904141203196.png" alt="image-20240904141203196" style="zoom:50%;" />
|
||||
|
||||
- Felix
|
||||
- 管理网络接口
|
||||
- 编写路由
|
||||
- 编写ACL
|
||||
- 报告状态
|
||||
- bird(BGPClient)
|
||||
- BGPClient将通过BGP协议⼴播告诉剩余calico节点,从而实现网络互通
|
||||
- confd
|
||||
- 通过监听etcd以了解BGP配置和全局默认值的更改。Confd根据ETCD中数据的更新,动态生成BIRD配置文件。当配置文件更改时,confd触发BIRD重新加载新文件
|
||||
|
||||
### VXLAN
|
||||
|
||||
- VXLAN,即Virtual Extensible LAN(虚拟可扩展局域网),是Linux本身支持的一网种网络虚拟化技术。VXLAN可以完全在内核态实现封装和解封装工作,从而通过“隧道”机制,构建出覆盖网络(OverlayNetwork)
|
||||
- 基于三层的”二层“通信,层即vxlan包封装在udp数据包中,要求udp在k8s节点间三层可达;
|
||||
- 二层即vxlan封包的源mac地址和目的mac地址是自己的vxlan设备mac和对端vxlan设备mac实现通讯。
|
||||
|
||||

|
||||
|
||||
- 数据包封包:封包,在vxlan设备上将pod发来的数据包源、目的mac替换为本机vxlan网卡和对端节点vxlan 网卡的mac。外层udp目的ip地址根据路由和对端vxlan的mac查fdb表获取
|
||||
|
||||
- 优势:只要k8s节点间三层互通,可以跨网段,对主机网关路由没有特殊要求。各个node节点通过vxlan设备实现基于三层的”二层”互通,三层即vxlan包封装在udp数据包中,要求udp在k8s节点间三层可达;二层即vxlan封包的源mac地址和目的mac地址是自己的vxlan设备mac和对端vxlan设备mac
|
||||
|
||||
- 缺点:需要进行vxlan的数据包封包和解包会存在一定的性能损耗
|
||||
|
||||

|
||||
|
||||
配置方法
|
||||
|
||||
```yaml
|
||||
# 在calico的配置文件中。如下配置
|
||||
# Auto-detect the BGP IP address.
|
||||
- name: IP
|
||||
value: "autodetect"
|
||||
# Enable IPIP
|
||||
- name: CALICO_IPV4POOL_IPIP
|
||||
value: "Never"
|
||||
# Enable or Disable VXLAN on the default IP pool.
|
||||
- name: CALICO_IPV4POOL_VXLAN
|
||||
value: "Always"
|
||||
# Enable or Disable VXLAN on the default IPv6 IP pool.
|
||||
- name: CALICO_IPV6POOL_VXLAN
|
||||
value: "Always"
|
||||
|
||||
# 分割线========================
|
||||
# calico_backend: "bird"
|
||||
calico_backend: "vxlan"
|
||||
|
||||
|
||||
# - -felix-live
|
||||
# - -bird-live
|
||||
```
|
||||
|
||||
查看验证
|
||||
|
||||
<img src="pod与网络/image-20240904150012585.png" alt="image-20240904150012585" style="zoom: 80%;" />
|
||||
|
||||
VXLAN不需要BGP来建立节点间的邻接关系
|
||||
|
||||
<img src="pod与网络/image-20240904150019409.png" alt="image-20240904150019409" style="zoom: 80%;" />
|
||||
|
||||
### IPIP
|
||||
|
||||
- Linux原生内核支持
|
||||
- IPIP隧道的工作原理是将源主机的IP数据包封装在一个新的IP数据包中,新的IP数据包的目的地址是隧道的另一端。在隧道的另一端,接收方将解封装原始IP数据包,并将其传递到目标主机。IPIP隧道可以在不同的网络之间建立连接,例如在IPv4网络和IPv6网络之间建立连接。
|
||||
|
||||
<img src="pod与网络/image-20240904145716982.png" alt="image-20240904145716982" style="zoom:33%;" />
|
||||
|
||||
- 数据包封包:封包,在tunl0设备上将pod发来的数据包的mac层去掉,留下ip层封包。外层数据包目的ip地址根据路由得到。
|
||||
- 优点:只要k8s节点间三层互通,可以跨网段,对主机网关路由没有特殊要求。
|
||||
- 缺点:需要进行IPIP的数据包封包和解包会存在一定的性能损耗
|
||||
|
||||

|
||||
|
||||
配置方法
|
||||
|
||||
```yaml
|
||||
# 在calico的配置文件中。如下配置
|
||||
# Auto-detect the BGP IP address.
|
||||
- name: IP
|
||||
value: "autodetect"
|
||||
# Enable IPIP
|
||||
- name: CALICO_IPV4POOL_IPIP
|
||||
value: "Always"
|
||||
# Enable or Disable VXLAN on the default IP pool.
|
||||
- name: CALICO_IPV4POOL_VXLAN
|
||||
value: "Never"
|
||||
# Enable or Disable VXLAN on the default IPv6 IP pool.
|
||||
- name: CALICO_IPV6POOL_VXLAN
|
||||
value: "Never"
|
||||
```
|
||||
|
||||
查看验证
|
||||
|
||||
<img src="pod与网络/image-20240904150123553.png" alt="image-20240904150123553" style="zoom:80%;" />
|
||||
|
||||
IPIP模式需要BGP来建立节点间的邻接关系,VXLAN不需要
|
||||
|
||||
<img src="pod与网络/image-20240904150127316.png" alt="image-20240904150127316" style="zoom:80%;" />
|
||||
|
||||
### BGP
|
||||
|
||||
边界网关协议(Border Gateway Protocol,BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP,BGP机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨⼲路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统。
|
||||
|
||||

|
||||
|
||||
- 数据包封包:不需要进行数据包封包
|
||||
- 优点:不用封包解包,通过BGP协议可实现pod网络在主机间的三层可达
|
||||
- 缺点:跨网段时,配置较为复杂网络要求较高,主机网关路由也需要充当BGPSpeaker。
|
||||
|
||||
配置方法
|
||||
|
||||
```yaml
|
||||
# 在calico的配置文件中。如下配置
|
||||
# Auto-detect the BGP IP address.
|
||||
- name: IP
|
||||
value: "autodetect"
|
||||
# Enable IPIP
|
||||
- name: CALICO_IPV4POOL_IPIP
|
||||
value: "Off"
|
||||
# Enable or Disable VXLAN on the default IP pool.
|
||||
- name: CALICO_IPV4POOL_VXLAN
|
||||
value: "Never"
|
||||
# Enable or Disable VXLAN on the default IPv6 IP pool.
|
||||
- name: CALICO_IPV6POOL_VXLAN
|
||||
value: "Never"
|
||||
```
|
||||
|
||||
查看验证
|
||||
|
||||
<img src="pod与网络/image-20240904151418487.png" alt="image-20240904151418487" style="zoom:80%;" />
|
||||
|
||||
<img src="pod与网络/image-20240904151425020.png" alt="image-20240904151425020" style="zoom:80%;" />
|
||||
|
||||
<img src="pod与网络/image-20240904151434684.png" alt="image-20240904151434684" style="zoom:80%;" />
|
673
Kubernetes/Pod控制器.md
Normal file
@@ -0,0 +1,673 @@
|
||||
# 控制器
|
||||
|
||||
在Kubernetes中运⾏了⼀系列控制器来确保集群的当前状态与期望状态保持⼀致,它们就是Kubernetes集群内部的管理控制中⼼或者说是”中⼼⼤脑”。例如,ReplicaSet控制器负责维护集群中运⾏的Pod数量;Node控制器负责监控节点的状态,并在节点出现故障时,执⾏⾃动化修复流程,确保集群始终处于预期的⼯作状态。
|
||||
|
||||

|
||||
|
||||
- ReplicationController 和 ReplicaSet
|
||||
- Deployment
|
||||
- DaemonSet
|
||||
- StateFulSet
|
||||
- Job/CronJob
|
||||
- Horizontal Pod Autoscaling
|
||||
|
||||
# ReplicationController
|
||||
|
||||
ReplicationController(RC)⽤来确保容器应⽤的副本数始终保持在⽤户定义的副本数,即如果有容器异常退出,会⾃动创建新的Pod来替代;⽽如果异常多出来的容器也会⾃动回收;
|
||||
|
||||
在新版本的Kubernetes中建议使⽤ReplicaSet(RS)来取代ReplicationController。ReplicaSet跟ReplicationController没有本质的不同,只是名字不⼀样,并且ReplicaSet⽀持集合式的selector;
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ReplicationController
|
||||
metadata:
|
||||
name: rc-demo
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
app: rc-demo
|
||||
template:
|
||||
metadata:
|
||||
name: rc-demo
|
||||
labels:
|
||||
app: rc-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: rc-demo-container
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
ports:
|
||||
- containerPort: 80
|
||||
|
||||
# kubectl delete pod rc-demo-fl7vb
|
||||
# kubectl label pod rc-demo-fl7vb app=rc-demo1 --overwrite
|
||||
```
|
||||
|
||||
RS控制器
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: ReplicaSet
|
||||
metadata:
|
||||
name: rc-ml-demo
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: rc-ml-demo
|
||||
template:
|
||||
metadata:
|
||||
name: rc-ml-demo
|
||||
labels:
|
||||
app: rc-ml-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: rc-ml-demo-container
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
`selector.matchExpressions`
|
||||
rs在标签选择器上,除了可以定义键值对的选择形式,还支持matchExpressions字段,可以提供多种选择。
|
||||
目前支持的操作包括:
|
||||
|
||||
- In:label的值在某个列表中
|
||||
- NotIn:label的值不在某个列表中
|
||||
- Exists:某个label存在
|
||||
- DoesNotExist:某个label不存在
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: ReplicaSet
|
||||
metadata:
|
||||
name: rc-me-demo
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: Exists
|
||||
template:
|
||||
metadata:
|
||||
name: rc-me-demo
|
||||
labels:
|
||||
app: rc-me-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: rc-me-demo-container
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: ReplicaSet
|
||||
metadata:
|
||||
name: rc-me-in-demo
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- spring-k8s
|
||||
- xixixi
|
||||
template:
|
||||
metadata:
|
||||
name: rc-me-in-demo
|
||||
labels:
|
||||
app: rc-me-in-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: rc-me-in-demo-container
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
# Deployment
|
||||
|
||||
声明性的东⻄是对终结果的陈述,表明意图⽽不是实现它的过程。在Kubernetes中,这就是说“应该有⼀个包含三个Pod的ReplicaSet”。
|
||||
命令式充当命令。声明式是被动的,⽽命令式是主动且直接的:“创建⼀个包含三个Pod的ReplicaSet”。
|
||||
|
||||
```bash
|
||||
$ kubectl replace -f deployment.yaml
|
||||
|
||||
$ kubectl apply -f deployment.yaml
|
||||
|
||||
$ kubectl diff -f deployment.yaml
|
||||
```
|
||||
|
||||
替换⽅式
|
||||
- kubectl replace:使⽤新的配置完全替换掉现有资源的配置。这意味着新配置将覆盖现有资源的所有字段和属性,包括未指定的字段,会导致整个资源的替换
|
||||
- kubectl apply:使⽤新的配置部分地更新现有资源的配置。它会根据提供的配置文件或参数,只更新与新配置中不同的部分,⽽不会覆盖整个资源的配置
|
||||
|
||||
字段级别的更新
|
||||
- kubectl replace:由于是完全替换,所以会覆盖所有字段和属性,⽆论是否在新配置中指定
|
||||
- kubectl apply:只更新与新配置中不同的字段和属性,保留未指定的字段不受影响
|
||||
|
||||
部分更新
|
||||
- kubectl replace:不⽀持部分更新,它会替换整个资源的配置
|
||||
- kubectl apply:⽀持部分更新,只会更新新配置中发⽣变化的部分,保留未指定的部分不受影响
|
||||
|
||||
与其他配置的影响
|
||||
- kubectl replace:不考虑其他资源配置的状态,直接替换资源的配置
|
||||
- kubectl apply:可以结合使⽤-f或-k参数,从文件或⽬录中读取多个资源配置,并根据当前集群中的资源状态进⾏更新
|
||||
|
||||
## Deployment介绍
|
||||
|
||||
Deployment为Pod和ReplicaSet提供了⼀个声明式定义(declarative)⽅法,⽤来替代以前的ReplicationController来⽅便的管理应⽤。典型的应⽤场景包括:
|
||||
|
||||
- 定义Deployment来创建Pod和ReplicaSet
|
||||
- 滚动升级和回滚应⽤
|
||||
- 扩容和缩容
|
||||
- 暂停和继续Deployment
|
||||
|
||||
<img src="Pod控制器/image-20240911095809938.png" alt="image-20240911095809938" style="zoom: 50%;" />
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp-deploy
|
||||
name: myapp-deploy
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp-deploy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp-deploy
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
## 更新策略
|
||||
|
||||
Deployment可以保证在升级时只有⼀定数量的Pod是down的。默认的,它会确保⾄少有比期望的Pod数量少⼀个是up状态(最多⼀个不可⽤)
|
||||
|
||||
Deployment同时也可以确保只创建出超过期望数量的⼀定数量的Pod。默认的,它会确保最多比期望的Pod数量多⼀个的Pod是up的(最多1个surge)
|
||||
|
||||
未来的Kuberentes版本中,将从1-1变成25%-25%。目前的版本已经支持。
|
||||
|
||||
kubectlexplaindeploy.spec.strategy.type
|
||||
|
||||
- Recreate
|
||||
- 在创建出新的Pod之前会先杀掉所有已存在的Pod
|
||||
|
||||
- rollingUpdate
|
||||
- 滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
|
||||
|
||||
- maxSurge:指定超出副本数有⼏个,两种⽅式:1、指定数量2、百分比
|
||||
|
||||
- maxUnavailable:最多有⼏个不可⽤
|
||||
|
||||
|
||||
```bash
|
||||
$ kubectl create -f deployment.yaml --record
|
||||
# --record 参数可以记录命令,可以看到每次revision的变化
|
||||
|
||||
$ kubectl scale deployment myapp-deploy --replicas 10
|
||||
|
||||
$ kubectl autoscale deployment myapp-deploy --min=10 --max=15 --cpu-percent=80
|
||||
|
||||
$ kubectl set image deployment/myapp-deploy myapp=aaronxudocker/myapp:v2.0
|
||||
|
||||
$ kubectl rollout history deployment/myapp-deploy
|
||||
|
||||
$ kubectl rollout undo deployment/myapp-deploy
|
||||
```
|
||||
|
||||
可以通过设置`.spec.revisionHistoryLimit`项来指定deployment最多保留多少revision历史记录。默认的会保留所有的revision;如果将该项设置为0,Deployment就不允许回退了
|
||||
|
||||
## 金丝雀部署
|
||||
|
||||
⾦丝雀部署的名字灵感来源于17世纪英国矿井⼯⼈使⽤⾦丝雀作为⽡斯检测指标的传统⽅法。⾦丝雀对⽡斯这种⽓体⼗分敏感,空⽓中哪怕有极其微量的⽡斯,⾦丝雀也会停⽌歌唱。⽽当⽡斯含量超过⼀定限度时,虽然⼈类毫⽆察觉,⾦丝雀却早已毒发⾝亡。在采矿设备相对简陋的条件下,⼯⼈们每次下井都会带上⼀只⾦丝雀作为“⽡斯检测指标”,以便在危险状况下紧急撤离。
|
||||
|
||||
⾦丝雀部署的核⼼思想是在实际运⾏环境中的⼀⼩部分⽤户或流量上测试新版本的软件,⽽⼤部分⽤户或流量仍然使⽤旧版本。通过对新版本进⾏有限范围的实时测试和监控,可以及早发现潜在的问题,并减少对整个系统的冲击。
|
||||
|
||||
<img src="Pod控制器/image-20240911143520378.png" alt="image-20240911143520378" style="zoom:33%;" />
|
||||
|
||||
```bash
|
||||
$ kubectl patch deployment myapp-deploy -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
|
||||
# 允许pod多出预期1个,不允许少一个
|
||||
|
||||
$ kubectl patch deployment myapp-deploy --patch '{"spec": {"template": {"spec": {"containers": [{"name": "myapp","image":"aaronxudocker/myapp:v2.0"}]}}}}' && kubectl rollout pause deploy myapp-deploy
|
||||
# 修改镜像为v2.0版本,并且立马停止回滚,可以看到pod数量复合上面的设置
|
||||
|
||||
$ kubectl rollout resume deploy myapp-deploy
|
||||
# 恢复回滚动作
|
||||
```
|
||||
|
||||
回滚相关的命令
|
||||
|
||||
```bash
|
||||
$ kubectl rollout status deployment myapp-deploy
|
||||
# 查看上次回滚的状态
|
||||
|
||||
$ kubectl rollout history deployment/myapp-deploy
|
||||
# 查看回滚的历史记录,需要配合--record使用
|
||||
|
||||
$ kubectl rollout undo deployment/myapp-deploy --to-revision=2
|
||||
# 状态回退到李四记录里面的2的状态
|
||||
|
||||
$ kubectl rollout pause deployment/myapp-deploy
|
||||
# 暂停回滚
|
||||
```
|
||||
|
||||
# DaemonSet
|
||||
|
||||
DaemonSet确保全部(或者⼀些)Node上运⾏⼀个Pod的副本。当有Node加入集群时,也会为他们新增⼀个Pod。当有Node从集群移除时,这些Pod也会被回收。删除DaemonSet将会删除它创建的所有Pod
|
||||
|
||||
使⽤DaemonSet的⼀些典型⽤法:
|
||||
- 运⾏集群存储daemon,例如在每个Node上运⾏`glusterd`、`ceph`
|
||||
- 在每个Node上运⾏⽇志收集daemon,例如`fluentd`、`logstash`
|
||||
- 在每个Node上运⾏监控daemon,例如PrometheusNode Exporter、`collectd`、Datadog代理、NewRelic代理,或Ganglia`gmond`
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: deamonset-demo
|
||||
namespace: default
|
||||
labels:
|
||||
app: deamonset-demo
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: deamonset-demo
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: deamonset-demo
|
||||
spec:
|
||||
containers:
|
||||
- name: deamonset-demo
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
```
|
||||
|
||||
# Job
|
||||
|
||||
Job负责批处理任务,即仅执⾏⼀次的任务,它保证批处理任务的⼀个或多个Pod成功结束
|
||||
|
||||
特殊说明
|
||||
- spec.template格式同Pod
|
||||
- RestartPolicy仅⽀持Never或OnFailure
|
||||
- 单个Pod时,默认Pod成功运⾏后Job即结束
|
||||
- `.spec.completions`标志Job结束需要成功运⾏的Pod个数,默认为1
|
||||
- `.spec.parallelism`标志并⾏运⾏的Pod的个数,默认为1
|
||||
- `spec.activeDeadlineSeconds`标志失败Pod的重试最⼤时间,超过这个时间不会继续重试
|
||||
|
||||
案例:使用马青公式计算圆周率后一千位,可以用来看下节点的计算能力
|
||||
|
||||
这个公式由英国天文学教授约翰·⻢青于1706年发现。他利⽤这个公式计算到了100位的圆周率。⻢青公式每计算⼀项可以得到1.4位的⼗进制精度。因为它的计算过程中被乘数和被除数都不⼤于⻓整数,所以可以很容易地在计算机上编程实现
|
||||
$$
|
||||
\frac{\pi}{4} = 4 \tan^{-1}\left(\frac{1}{5}\right) - \tan^{-1}\left(\frac{1}{239}\right)
|
||||
$$
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: job-demo
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
name: job-demo-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: job-demo
|
||||
image: aaronxudocker/tools:maqingpythonv1
|
||||
restartPolicy: Never
|
||||
```
|
||||
|
||||
Job负责批处理任务,即仅执⾏⼀次的任务,它保证批处理任务的⼀个或多个Pod成功结束
|
||||
|
||||
## 错误的Job任务
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: rand
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
name: rand
|
||||
spec:
|
||||
containers:
|
||||
- name: rand
|
||||
image: aaronxudocker/tools:randexitv1
|
||||
args: ["--exitcode=1"]
|
||||
restartPolicy: Never
|
||||
```
|
||||
|
||||
Job控制器会记录成功的次数
|
||||
|
||||
```bash
|
||||
$ kubectl get job
|
||||
NAME COMPLETIONS DURATION AGE
|
||||
rand 0/1 30s 30s
|
||||
```
|
||||
|
||||
改为产生随机返回值
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: rand
|
||||
spec:
|
||||
completions: 10
|
||||
parallelism: 5
|
||||
template:
|
||||
metadata:
|
||||
name: rand
|
||||
spec:
|
||||
containers:
|
||||
- name: rand
|
||||
image: aaronxudocker/tools:randexitv1
|
||||
restartPolicy: Never
|
||||
```
|
||||
|
||||
可以看到并行启动5个pod,直到成功为止
|
||||
|
||||
```bash
|
||||
$ kubectl get job -w
|
||||
NAME COMPLETIONS DURATION AGE
|
||||
rand 2/10 24s 24s
|
||||
rand 2/10 50s 50s
|
||||
rand 2/10 52s 52s
|
||||
rand 2/10 58s 58s
|
||||
rand 2/10 59s 59s
|
||||
rand 3/10 59s 59s
|
||||
rand 3/10 60s 60s
|
||||
rand 5/10 60s 60s
|
||||
rand 5/10 61s 61s
|
||||
rand 5/10 62s 62s
|
||||
rand 5/10 67s 67s
|
||||
rand 5/10 68s 68s
|
||||
rand 8/10 68s 68s
|
||||
rand 8/10 69s 69s
|
||||
rand 8/10 69s 69s
|
||||
|
||||
|
||||
$ kubectl get job -o yaml
|
||||
......
|
||||
spec:
|
||||
backoffLimit: 6
|
||||
# 6次尝试失败,就达到尝试上限
|
||||
```
|
||||
|
||||
# CronJob
|
||||
|
||||
CronJob管理基于时间的Job,即:
|
||||
- 在给定时间点只运⾏⼀次
|
||||
- 周期性地在给定时间点运⾏
|
||||
|
||||
使⽤条件:当前使⽤的Kubernetes集群,版本>=1.8(对CronJob)
|
||||
|
||||
典型的⽤法如下所⽰:
|
||||
- 在给定的时间点调度Job运⾏
|
||||
- 创建周期性运⾏的Job,例如:数据库备份、发送邮件
|
||||
|
||||
|
||||
|
||||
- `.spec.schedule`:调度,必需字段,指定任务运⾏周期,格式同Cron
|
||||
- `.spec.jobTemplate`:Job模板,必需字段,指定需要运⾏的任务,格式同Job
|
||||
- `.spec.startingDeadlineSeconds`:启动Job的期限(秒级别),该字段是可选的。如果因为任何原因⽽错过了被调度的时间,那么错过执⾏时间的Job将被认为是失败的。如果没有指定,则没有期限
|
||||
- `.spec.concurrencyPolicy`:并发策略,该字段也是可选的。它指定了如何处理被CronJob创建的Job的并发执⾏。只允许指定下⾯策略中的⼀种:
|
||||
- `Allow`(默认):允许并发运⾏Job
|
||||
- `Forbid`:禁⽌并发运⾏,如果前⼀个还没有完成,则直接跳过下⼀个
|
||||
- `Replace`:取消当前正在运⾏的Job,⽤⼀个新的来替换
|
||||
- 注意,当前策略只能应⽤于同⼀个CronJob创建的Job。如果存在多个CronJob,它们创建的Job之间总是允许并发运⾏。
|
||||
|
||||
- `.spec.suspend`:挂起,该字段也是可选的。如果设置为`true`,后续所有执⾏都会被挂起。它对已经开始执⾏的Job不起作⽤。默认值为`false`
|
||||
- `.spec.successfulJobsHistoryLimit`和`.spec.failedJobsHistoryLimit`:历史限制,是可选的字段。它们指定了可以保留多少完成和失败的Job。默认情况下,它们分别设置为`3`和`1`。设置限制的值为`0`,相关类型的Job完成后将不会被保留
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: cronjob-demo
|
||||
spec:
|
||||
schedule: "*/1 * * * *"
|
||||
jobTemplate:
|
||||
spec:
|
||||
completions: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: cronjob-demo-container
|
||||
image: aaronxudocker/tools:busybox
|
||||
args:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- date; echo Hello from the Kubernetes cluster
|
||||
restartPolicy: OnFailure
|
||||
```
|
||||
|
||||
创建job操作应该是幂等的
|
||||
|
||||
# Horizontal Pod Autoscaler(HPA)
|
||||
|
||||
在前面的课程中,我们已经可以实现通过手工执行`kubectl scale`命令实现Pod扩容或缩容,但是这显然不符合Kubernetes的定位目标--自动化、智能化。 Kubernetes期望可以实现通过监测Pod的使用情况,实现pod数量的自动调整,于是就产生了Horizontal Pod Autoscaler(HPA)这种控制器。
|
||||
|
||||
HPA可以获取每个Pod利用率,然后和HPA中定义的指标进行对比,同时计算出需要伸缩的具体值,最后实现Pod的数量的调整。其实HPA与之前的Deployment一样,也属于一种Kubernetes资源对象,它通过追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数,这是HPA的实现原理。
|
||||
|
||||
<img src="Pod控制器/image-20240912140819583.png" alt="image-20240912140819583" style="zoom:33%;" />
|
||||
|
||||
查看pod的资源
|
||||
|
||||
```bash
|
||||
# 由于没安装metrics服务,所以无法查看pod资源情况
|
||||
$ kubectl top pod myapp-deploy-57bff895d5-cvlmg
|
||||
error: Metrics API not available
|
||||
```
|
||||
|
||||
安装metrics-server
|
||||
|
||||
```bash
|
||||
$ wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.7.2/components.yaml
|
||||
|
||||
# 修改配置文件
|
||||
- args:
|
||||
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname,InternalDNS,ExternalDNS
|
||||
- --kubelet-insecure-tls
|
||||
image: registry.k8s.io/metrics-server/metrics-server:v0.7.2
|
||||
|
||||
$ kubectl apply -f components.yaml
|
||||
|
||||
$ kubectl get pod -n kube-system |grep metrics
|
||||
metrics-server-5c7fbc6ff6-fssfd 1/1 Running 0 2m42s
|
||||
|
||||
# 使用kubectl top node 查看资源使用情况
|
||||
$ kubectl top node
|
||||
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
|
||||
master01 116m 2% 1943Mi 55%
|
||||
node01 48m 1% 961Mi 27%
|
||||
node02 61m 1% 1161Mi 32%
|
||||
|
||||
$ kubectl top pod myapp-deploy-57bff895d5-cvlmg
|
||||
NAME CPU(cores) MEMORY(bytes)
|
||||
myapp-deploy-57bff895d5-cvlmg 0m 4Mi
|
||||
```
|
||||
|
||||
准备deployment和service资源
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-pod
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
resources:
|
||||
limits:
|
||||
cpu: "1"
|
||||
requests:
|
||||
cpu: "100m"
|
||||
```
|
||||
|
||||
创建service并且查看
|
||||
|
||||
```bash
|
||||
$ kubectl expose deployment nginx --type=NodePort --port=80
|
||||
|
||||
$ kubectl get deployment,pod,svc
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/nginx 1/1 1 1 114s
|
||||
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/nginx-7b4664bb57-pgllw 1/1 Running 0 114s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/nginx NodePort 10.8.51.98 <none> 80:30482/TCP 37s
|
||||
```
|
||||
|
||||
创建HPA资源
|
||||
|
||||
```yaml
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: hpa-demo
|
||||
spec:
|
||||
minReplicas: 1 #最小pod数量
|
||||
maxReplicas: 10 #最大pod数量
|
||||
behavior:
|
||||
scaleUp:
|
||||
stabilizationWindowSeconds: 10 # 在连续10秒内稳定后才考虑进一步扩展操作
|
||||
policies:
|
||||
- type: Percent
|
||||
value: 100 # 当超过当前副本数的100%才进行扩展
|
||||
periodSeconds: 3 # 两次扩容之间的最小时间间隔
|
||||
scaleDown:
|
||||
stabilizationWindowSeconds: 300 # 在连续300秒内稳定后才考虑缩减操作
|
||||
policies:
|
||||
- type: Percent
|
||||
value: 10 # 当低于当前副本数的10%才进行缩减
|
||||
periodSeconds: 3 # 两次缩减之间的最小时间间隔
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 10 # CPU平均利用率目标设为10%
|
||||
scaleTargetRef: # 指定要控制的nginx信息
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: nginx
|
||||
```
|
||||
|
||||
查看hpa资源
|
||||
|
||||
```bash
|
||||
$ kubectl get hpa -w
|
||||
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 1 20s
|
||||
```
|
||||
|
||||
使用压力测试工具
|
||||
|
||||
```bash
|
||||
$ ab -c 1000 -n 1000000 http://192.168.173.100:30482/
|
||||
|
||||
$ kubectl get hpa -w
|
||||
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 1 20s
|
||||
hpa-demo Deployment/nginx 1%/10% 1 10 1 105s
|
||||
hpa-demo Deployment/nginx 366%/10% 1 10 1 2m
|
||||
hpa-demo Deployment/nginx 522%/10% 1 10 2 2m15s
|
||||
hpa-demo Deployment/nginx 352%/10% 1 10 4 2m30s
|
||||
hpa-demo Deployment/nginx 189%/10% 1 10 8 2m45s
|
||||
hpa-demo Deployment/nginx 103%/10% 1 10 10 3m
|
||||
hpa-demo Deployment/nginx 68%/10% 1 10 10 3m15s
|
||||
```
|
||||
|
||||
压力测试停止之后
|
||||
|
||||
```bash
|
||||
$ kubectl get hpa -w
|
||||
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 10 8m45s
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 9 9m
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 8 9m15s
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 7 9m30s
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 6 9m45s
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 5 10m
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 4 10m
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 3 10m
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 2 10m
|
||||
hpa-demo Deployment/nginx 0%/10% 1 10 1 11m
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
BIN
Kubernetes/Pod控制器/image-20240910143437460.png
Normal file
After Width: | Height: | Size: 295 KiB |
BIN
Kubernetes/Pod控制器/image-20240911095809938.png
Normal file
After Width: | Height: | Size: 208 KiB |
BIN
Kubernetes/Pod控制器/image-20240911143520378.png
Normal file
After Width: | Height: | Size: 370 KiB |
BIN
Kubernetes/Pod控制器/image-20240912140819583.png
Normal file
After Width: | Height: | Size: 74 KiB |
766
Kubernetes/Pod生命周期.md
Normal file
@@ -0,0 +1,766 @@
|
||||
# Pod生命周期
|
||||
|
||||

|
||||
|
||||
init容器与普通的容器非常像,除了如下两点:
|
||||
|
||||
- init容器总是运行到成功完成为止
|
||||
- 每个init容器都必须在下一个init容器启动之前成功完成
|
||||
|
||||
如果Pod的Init容器失败,Kubernetes会不断地重启该Pod,直到Init容器成功为止。然而,如果Pod对应的restartPolicy为Never,它不会重新启动
|
||||
|
||||
## 检测initC的阻塞性
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: initc-1
|
||||
labels:
|
||||
name: initc
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-container
|
||||
image: centos:7
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
command: ['sh', '-c', 'echo The app is running && sleep 10']
|
||||
initContainers:
|
||||
- name: init-myservice
|
||||
image: aaronxudocker/tools:busybox
|
||||
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
|
||||
- name: init-mydb
|
||||
image: aaronxudocker/tools:busybox
|
||||
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
|
||||
```
|
||||
|
||||
```bash
|
||||
# 查看日志,看到不停的在尝试
|
||||
$ kubectl logs initc-1 -c init-myservice
|
||||
|
||||
# 创建svc资源,会通过CoreDNS自动将myservice解析成功,详解看后面的service部分
|
||||
$ kubectl create svc clusterip myservice --tcp=80:80
|
||||
```
|
||||
|
||||
如果initc执行失败了,那么就会重新执行所有的initc
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: initc-2
|
||||
labels:
|
||||
name: initc
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-container
|
||||
image: centos:7
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
command: ['sh', '-c', 'echo The app is running && sleep 10']
|
||||
initContainers:
|
||||
- name: init-myservice
|
||||
image: aaronxudocker/tools:busybox
|
||||
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
|
||||
- name: randexit
|
||||
image: aaronxudocker/tools:randexitv1
|
||||
args: ['--exitcode=1']
|
||||
```
|
||||
|
||||
```bash
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
initc-1 0/1 Init:1/2 0 16m
|
||||
initc-2 0/1 Init:Error 5 (97s ago) 3m42s
|
||||
$ kubectl logs initc-2 -c randexit
|
||||
休眠 4 秒,返回码为 1!
|
||||
```
|
||||
|
||||
如果我们让initc的返回码直接为0,那么就可以看到pod正常启动
|
||||
|
||||
```bash
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
initc-1 0/1 Init:1/2 0 19m
|
||||
initc-2 1/1 Running 1 (7s ago) 72s
|
||||
```
|
||||
|
||||
- InitC与应用容器具备不同的镜像,可以把一些危险的工具放置在initC中,进行使用
|
||||
- initC多个之间是线性启动的,所以可以做一些延迟性的操作
|
||||
- initC无法定义readinessProbe,其它以外同应用容器定义无异
|
||||
|
||||
# Pod探针
|
||||
|
||||
探针是由kubelet对容器执行的定期诊断。要执行诊断,kubelet调用由容器实现的Handler。有三种类型的处理程序:
|
||||
|
||||
- ExecAction:在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功
|
||||
- TCPSocketAction:对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的
|
||||
- HTTPGetAction:对指定的端口和路径上的容器的IP地址执行HTTPGet请求。如果响应的状态码⼤于等于200且小于400,则诊断被认为是成功的
|
||||
|
||||
每次探测都将获得以下三种结果之一:
|
||||
|
||||
- 成功:容器通过了诊断。
|
||||
- 失败:容器未通过诊断。
|
||||
- 未知:诊断失败,因此不会采取任何行动
|
||||
|
||||
## 探针的分类
|
||||
|
||||
- startupProbe:开始探针,开始检测吗?
|
||||
- livenessProbe:存活探针,还活着吗?
|
||||
- readinessProbe:就绪探针,准备提供服务了吗?
|
||||
|
||||
### readinessProbe就绪探针
|
||||
|
||||
介绍:k8s通过添加就绪探针,解决尤其是在扩容时保证提供给用户的服务都是可用的。
|
||||
|
||||
> 选项说明
|
||||
> - initialDelaySeconds:容器启动后要等待多少秒后就探针开始工作,单位“秒”,默认是0秒,最小值是0
|
||||
> - periodSeconds:执行探测的时间间隔(单位是秒),默认为10s,单位“秒”,最小值是1
|
||||
> - timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为1s,单位“秒”,最小值是1
|
||||
> - successThreshold:探针检测失败后认为成功的最小连接成功次数,默认值为1。必须为1才能激活和启动。最小值为1。
|
||||
> - failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为3,最小值为1。
|
||||
|
||||
#### 就绪探针实验
|
||||
|
||||
- 基于 HTTP GET 方式
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: readiness-httpget-pod
|
||||
labels:
|
||||
name: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: readiness-httpget-container
|
||||
image: nginx:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 80
|
||||
path: /index1.html
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
```bash
|
||||
# 当前处于没有就绪的状态
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
readiness-httpget-pod 0/1 Running 0 4m16s
|
||||
|
||||
# 创建一个index1.html
|
||||
$ kubectl exec -it readiness-httpget-pod -c readiness-httpget-container -- /bin/bash
|
||||
root@readiness-httpget-pod:/# echo "hehe" > /usr/share/nginx/html/index1.html
|
||||
|
||||
# 查看就已经处于就绪的状态了
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
readiness-httpget-pod 1/1 Running 0 5m40s
|
||||
|
||||
# 在运行过程中,就绪探测一直存在,如果不满足条件,会回到未就绪的情况
|
||||
```
|
||||
|
||||
- 基于 EXEC 方式
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: readiness-exec-pod
|
||||
labels:
|
||||
name: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: readiness-exec-container
|
||||
image: aaronxudocker/tools:busybox
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["/bin/sh", "-c", "touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep 3600"]
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: ["test", "-e", "/tmp/live"]
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
```bash
|
||||
# 可以看到在60秒后就变成非就绪状态了
|
||||
$ kubectl get pod -w
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
readiness-exec-pod 1/1 Running 0 7s
|
||||
readiness-exec-pod 0/1 Running 0 69s
|
||||
```
|
||||
|
||||
基于TCP Check方式
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: readiness-tcp-pod
|
||||
labels:
|
||||
name: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: readiness-tcp-container
|
||||
image: nginx:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
#### 就绪探针流量测试
|
||||
|
||||
<img src="Pod生命周期/image-20240906140721572.png" alt="image-20240906140721572" style="zoom: 25%;" />
|
||||
|
||||
在匹配可用pod的时候,标签必须匹配,状态必须是就绪状态。
|
||||
|
||||
```yaml
|
||||
# pod-1.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-1
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-1
|
||||
image: nginx:latest
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
|
||||
# pod-2.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-2
|
||||
labels:
|
||||
app: myapp
|
||||
version: v1
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-1
|
||||
image: nginx:latest
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
|
||||
# 确认状态已经就绪
|
||||
$ kubectl get pod --show-labels
|
||||
NAME READY STATUS RESTARTS AGE LABELS
|
||||
pod-1 1/1 Running 0 2m31s app=myapp
|
||||
pod-2 1/1 Running 0 32s app=myapp,version=v1
|
||||
```
|
||||
|
||||
创建service资源
|
||||
|
||||
```bash
|
||||
# 注意myapp就是标签为app=myapp的pod
|
||||
# 此处不需要理解,后面会细讲,只是用来验证就绪探针对流量的影响
|
||||
# 此处的作用是形成多个pod的负载均衡
|
||||
$ kubectl create svc clusterip myapp --tcp=80:80
|
||||
service/myapp created
|
||||
$ kubectl get svc
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 46h
|
||||
myapp ClusterIP 10.8.74.201 <none> 80/TCP 6s
|
||||
```
|
||||
|
||||
将两个pod中的主页文件修改一下,用来作为区分
|
||||
|
||||
```bash
|
||||
# 如果pod中只有一个main容器,那么在exec的时候就不需要指定容器
|
||||
$ kubectl exec -it pod-1 -- /bin/bash
|
||||
root@pod-1:/# echo pod-1 > /usr/share/nginx/html/index.html
|
||||
$ kubectl exec -it pod-2 -- /bin/bash
|
||||
root@pod-2:/# echo pod-2 > /usr/share/nginx/html/index.html
|
||||
```
|
||||
|
||||
验证负载均衡的状态
|
||||
|
||||
```bash
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
$ curl 10.8.74.201
|
||||
pod-1
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
```
|
||||
|
||||
创建一个label为 `app: test` 的pod,看下是否能被匹配
|
||||
|
||||
```yaml
|
||||
# 3.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-3
|
||||
labels:
|
||||
app: test
|
||||
version: v1
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-1
|
||||
image: nginx:latest
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
查看pod状态,修改 `pod-3` 的网页内容
|
||||
|
||||
```bash
|
||||
$ kubectl get pod --show-labels
|
||||
NAME READY STATUS RESTARTS AGE LABELS
|
||||
pod-1 1/1 Running 0 11m app=myapp
|
||||
pod-2 1/1 Running 0 9m57s app=myapp,version=v1
|
||||
pod-3 1/1 Running 0 51s app=test,version=v1
|
||||
|
||||
$ kubectl exec -it pod-3 -- /bin/bash
|
||||
root@pod-3:/# echo pod-3 > /usr/share/nginx/html/index.html
|
||||
```
|
||||
|
||||
验证负载均衡的状态,发现 `pod-3` 并不能被匹配上
|
||||
|
||||
```bash
|
||||
$ curl 10.8.74.201
|
||||
pod-1
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
$ curl 10.8.74.201
|
||||
pod-1
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
$ curl 10.8.74.201
|
||||
pod-1
|
||||
```
|
||||
|
||||
创建一个不满足就绪条件的 `pod-4`
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: pod-4
|
||||
labels:
|
||||
app: myapp
|
||||
version: v1
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-1
|
||||
image: nginx:latest
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 80
|
||||
path: /index1.html
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
修改主页内容
|
||||
|
||||
```bash
|
||||
$ kubectl exec -it pod-4 -- /bin/bash
|
||||
root@pod-4:/# echo pod-4 > /usr/share/nginx/html/index.html
|
||||
```
|
||||
|
||||
查看状态是未就绪的
|
||||
|
||||
```bash
|
||||
$ kubectl get pod --show-labels
|
||||
NAME READY STATUS RESTARTS AGE LABELS
|
||||
pod-1 1/1 Running 0 17m app=myapp
|
||||
pod-2 1/1 Running 0 15m app=myapp,version=v1
|
||||
pod-3 1/1 Running 0 6m49s app=test,version=v1
|
||||
pod-4 0/1 Running 0 41s app=myapp,version=v1
|
||||
```
|
||||
|
||||
验证负载均衡
|
||||
|
||||
```bash
|
||||
$ curl 10.8.74.201
|
||||
pod-1
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
$ curl 10.8.74.201
|
||||
pod-1
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
$ curl 10.8.74.201
|
||||
pod-1
|
||||
```
|
||||
|
||||
满足 `pod-4` 的就绪条件
|
||||
|
||||
```bash
|
||||
$ kubectl exec -it pod-4 -- /bin/bash
|
||||
root@pod-4:/# touch /usr/share/nginx/html/index1.html
|
||||
```
|
||||
|
||||
再次验证负载均衡
|
||||
|
||||
```bash
|
||||
$ curl 10.8.74.201
|
||||
pod-1
|
||||
$ curl 10.8.74.201
|
||||
pod-2
|
||||
$ curl 10.8.74.201
|
||||
pod-4
|
||||
```
|
||||
|
||||
### livenessProbe存活探针
|
||||
|
||||
介绍:k8s通过添加存活探针,解决虽然活着但是已经死了的问题。
|
||||
|
||||
> 选项说明
|
||||
> - initialDelaySeconds:容器启动后要等待多少秒后就探针开始工作,单位“秒”,默认是0秒,最小值是0
|
||||
> - periodSeconds:执行探测的时间间隔(单位是秒),默认为10s,单位“秒”,最小值是1
|
||||
> - timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为1s,单位“秒”,最小值是1
|
||||
> - successThreshold:探针检测失败后认为成功的最小连接成功次数,默认值为1。必须为1才能激活和启动。最小值为1。
|
||||
> - failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为3,最小值为1。
|
||||
|
||||
#### 存活探针实验
|
||||
|
||||
- 基于 Exec 方式
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: liveness-exec-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: liveness-exec-container
|
||||
image: aaronxudocker/tools:busybox
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ["/bin/sh", "-c", "touch /tmp/live; sleep 60; rm -rf /tmp/live; sleep 3600"]
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: ["test", "-e", "/tmp/live"]
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
一段时间以后,可以看到发生重启的事件
|
||||
|
||||
```bash
|
||||
$ kubectl get pod -w
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
liveness-exec-pod 1/1 Running 0 11s
|
||||
liveness-exec-pod 1/1 Running 1 (1s ago) 101s
|
||||
liveness-exec-pod 1/1 Running 2 (1s ago) 3m20s
|
||||
```
|
||||
|
||||
- 基于 HTTP Get 方式
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: liveness-httpget-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: liveness-httpget-container
|
||||
image: nginx:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
port: 80
|
||||
path: /index.html
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
timeoutSeconds: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
删除 `index.html` 文件,使其不满足存活探测条件
|
||||
|
||||
```bash
|
||||
# 在删除index.html之后,可以看到命令行退出了
|
||||
$ kubectl exec -it liveness-httpget-pod -- /bin/bash
|
||||
root@liveness-httpget-pod:/# rm -f /usr/share/nginx/html/index.html
|
||||
root@liveness-httpget-pod:/# command terminated with exit code 137
|
||||
```
|
||||
|
||||
重新查看pod状态,可以看到重启了
|
||||
|
||||
```bash
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
liveness-httpget-pod 1/1 Running 1 (48s ago) 2m39s
|
||||
```
|
||||
|
||||
在运行此pod的节点上查看docker的名字,容器名字是 `集群名-pod名-容器名-hash-重启次数(初始是0)`
|
||||
|
||||
```bash
|
||||
$ docker ps -a |grep liveness-exec-container
|
||||
18c5ba02d684 39286ab8a5e1 "/docker-entrypoint.…" About a minute ago Up About a minute k8s_liveness-exec-container_liveness-httpget-pod_default_aa36504e-23a9-48d1-988c-4de0398c474f_1
|
||||
54b3a04bd6b0 39286ab8a5e1 "/docker-entrypoint.…" 3 minutes ago Exited (0) About a minute ago k8s_liveness-exec-container_liveness-httpget-pod_default_aa36504e-23a9-48d1-988c-4de0398c474f_0
|
||||
```
|
||||
|
||||
- 基于 TCP Check 方式
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: liveness-tcp-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: liveness-tcp-container
|
||||
image: nginx:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
timeoutSeconds: 3
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
### startupProbe启动探针
|
||||
|
||||
介绍:k8s在1.16版本后增加startupProbe探针,主要解决在复杂的程序中readinessProbe、livenessProbe探针无法更好的判断程序是否启动、是否存活。
|
||||
|
||||
> 选项说明
|
||||
> - initialDelaySeconds:容器启动后要等待多少秒后就探针开始工作,单位“秒”,默认是0秒,最小值是0
|
||||
> - periodSeconds:执行探测的时间间隔(单位是秒),默认为10s,单位“秒”,最小值是1
|
||||
> - timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为1s,单位“秒”,最小值是1
|
||||
> - successThreshold:探针检测失败后认为成功的最小连接成功次数,默认值为1。必须为1才能激活和启动。最小值为1。
|
||||
> - failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为3,最小值为1。
|
||||
|
||||
#### 启动探针实验
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: startupprobe-1
|
||||
spec:
|
||||
containers:
|
||||
- name: startupprobe
|
||||
image: nginx:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 80
|
||||
path: /index2.html
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
startupProbe:
|
||||
httpGet:
|
||||
path: /index1.html
|
||||
port: 80
|
||||
periodSeconds: 10
|
||||
failureThreshold: 30
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
|
||||
# 应用程序将会有最多 5 分钟 failureThreshold * periodSeconds(30 * 10 = 300s)的时间来完成其启动过程。如果到超时都没有启动完成,就会重启。
|
||||
```
|
||||
|
||||
创建 `index1.html` 文件
|
||||
|
||||
```bash
|
||||
$ kubectl exec -it pod/startupprobe-1 -- /bin/bash
|
||||
root@startupprobe-1:/# touch /usr/share/nginx/index1.html
|
||||
|
||||
# 查看依旧是未就绪的状态
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
startupprobe-1 0/1 Running 0 42s
|
||||
|
||||
# 创建index2.html文件
|
||||
$ kubectl exec -it pod/startupprobe-1 -- /bin/bash
|
||||
root@startupprobe-1:/# touch /usr/share/nginx/index2.html
|
||||
|
||||
# 查看状态
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
startupprobe-1 1/1 Running 0 43s
|
||||
```
|
||||
|
||||
此时删掉启动探测的 `index1.html` 会怎样?
|
||||
|
||||
# Pod钩子
|
||||
|
||||
Podhook(钩子)是由Kubernetes管理的kubelet发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的⽣命周期之中。可以同时为Pod中的所有容器都配置hook
|
||||
|
||||
Hook的类型包括两种:
|
||||
- exec:执行一段命令
|
||||
- HTTP:发送HTTP请求
|
||||
|
||||
在k8s中,理想的状态是pod优雅释放,但是并不是每一个Pod都会这么顺利
|
||||
- Pod卡死,处理不了优雅退出的命令或者操作
|
||||
- 优雅退出的逻辑有BUG,陷入死循环
|
||||
- 代码问题,导致执行的命令没有效果
|
||||
|
||||
对于以上问题,k8s的Pod终止流程中还有一个"最多可以容忍的时间",即graceperiod(在pod.spec.terminationGracePeriodSeconds字段定义),这个值默认是30秒,当我们执行kubectl delete的时候也可以通过--grace-period参数显示指定一个优雅退出时间来覆盖Pod中的配置,如果我们配置的grace period超过时间之后,k8s就只能选择强制kill Pod。
|
||||
|
||||
值得注意的是,这与preStopHook和SIGTERM信号并行发⽣。k8s不会等待preStopHook完成。你的应用程序应在terminationGracePeriod之前退出。
|
||||
|
||||
## Pod钩子实验
|
||||
|
||||
- 基于 exec 方式
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: hook-exec-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: hook-exec-container
|
||||
image: nginx:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
postStart:
|
||||
exec:
|
||||
command: ["/bin/sh", "-c", "echo postStart > /usr/share/message"]
|
||||
preStop:
|
||||
exec:
|
||||
command: ["/bin/sh", "-c", "echo preStart > /usr/share/message"]
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
在这个pod的内部,写一个循环查看此文件的shell命令
|
||||
|
||||
```bash
|
||||
$ kubectl exec -it pod/hook-exec-pod -- /bin/bash
|
||||
root@hook-exec-pod:/# while true;
|
||||
> do
|
||||
> cat /usr/share/message
|
||||
> done
|
||||
|
||||
# 删除此pod就能看到结束的钩子信息了
|
||||
```
|
||||
|
||||
- 基于 HTTP Get 方式
|
||||
|
||||
```bash
|
||||
# 开启一个测试 webserver
|
||||
$ docker run -it --rm -p 1234:80 nginx:latest
|
||||
```
|
||||
|
||||
启动一个pod,然后再删除,查看nginx容器日志,可以看到记录了这两次的http请求
|
||||
|
||||
```yaml
|
||||
2024/09/06 07:35:23 [error] 29#29: *1 open() "/usr/share/nginx/html/poststarthook.html" failed (2: No such file or directory), client: 192.168.173.101, server: localhost, request: "GET /poststarthook.html HTTP/1.1", host: "192.168.173.100:1234"
|
||||
192.168.173.101 - - [06/Sep/2024:07:35:23 +0000] "GET /poststarthook.html HTTP/1.1" 404 153 "-" "kube-lifecycle/1.29" "-"
|
||||
2024/09/06 07:35:45 [error] 29#29: *1 open() "/usr/share/nginx/html/prestophook.html" failed (2: No such file or directory), client: 192.168.173.101, server: localhost, request: "GET /prestophook.html HTTP/1.1", host: "192.168.173.100:1234"
|
||||
192.168.173.101 - - [06/Sep/2024:07:35:45 +0000] "GET /prestophook.html HTTP/1.1" 404 153 "-" "kube-lifecycle/1.29" "-"
|
||||
```
|
||||
|
||||
# 总结
|
||||
|
||||
Pod⽣命周期中的initC、startupProbe、livenessProbe、readinessProbe、hook都是可以并且存在的,可以选择全部、部分或者完全不用。
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: lifecycle-pod
|
||||
labels:
|
||||
app: lifecycle-pod
|
||||
spec:
|
||||
containers:
|
||||
- name: busybox-container
|
||||
image: aaronxudocker/tools:busybox
|
||||
command: ["/bin/sh","-c","touch /tmp/live ; sleep 600; rm -rf /tmp/live; sleep 3600"]
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: ["test","-e","/tmp/live"]
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
lifecycle:
|
||||
postStart:
|
||||
httpGet:
|
||||
host: 192.168.173.100
|
||||
path: poststarthook.html
|
||||
port: 1234
|
||||
preStop:
|
||||
httpGet:
|
||||
host: 192.168.173.100
|
||||
path: prestophook.html
|
||||
port: 1234
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
- name: myapp-container
|
||||
image: nginx:latest
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
port: 80
|
||||
path: /index.html
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
timeoutSeconds: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 80
|
||||
path: /index1.html
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
initContainers:
|
||||
- name: init-myservice
|
||||
image: aaronxudocker/tools:busybox
|
||||
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
|
||||
- name: init-mydb
|
||||
image: aaronxudocker/tools:busybox
|
||||
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
|
||||
```
|
||||
|
||||
# 调度Pod
|
||||
|
||||

|
||||
|
BIN
Kubernetes/Pod生命周期/image-20240906095839924.png
Normal file
After Width: | Height: | Size: 286 KiB |
BIN
Kubernetes/Pod生命周期/image-20240906140721572.png
Normal file
After Width: | Height: | Size: 233 KiB |
BIN
Kubernetes/Pod生命周期/image-20240906204437000.png
Normal file
After Width: | Height: | Size: 421 KiB |
793
Kubernetes/Service.md
Normal file
@@ -0,0 +1,793 @@
|
||||
# 概念以及原理
|
||||
|
||||
Kubernetes`Service`定义了这样⼀种抽象:
|
||||
|
||||
⼀个`Pod`的逻辑分组,⼀种可以访问它们的策略,通常称为微服务。这⼀组`Pod`能够被`Service`访问到,通常是通过`LabelSelector`
|
||||
|
||||
<img src="Service/image-20240912140110844.png" alt="image-20240912140110844" style="zoom: 33%;" />
|
||||
|
||||
Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后**它会将最新的Service信息转换成对应的访问规则**。
|
||||
|
||||
<img src="Service/image-20240912152844652.png" alt="image-20240912152844652" style="zoom:33%;" />
|
||||
|
||||
|
||||
# 工作模式
|
||||
|
||||
kube-proxy目前支持三种工作模式:
|
||||
|
||||
## userspace模式
|
||||
|
||||
userspace模式下,kube-proxy会为每一个Service创建一个监听端口,发向Cluster IP的请求被Iptables规则重定向到kube-proxy监听的端口上,kube-proxy根据LB算法选择一个提供服务的Pod并和其建立链接,以将请求转发到Pod上。 该模式下,kube-proxy充当了一个四层负责均衡器的角色。由于kube-proxy运行在userspace中,在进行转发处理时会增加内核和用户空间之间的数据拷贝,虽然比较稳定,但是效率比较低。
|
||||
|
||||
<img src="Service/image-20240912170627727.png" alt="image-20240912170627727" style="zoom:33%;" />
|
||||
|
||||
## iptables模式
|
||||
|
||||
iptables模式下,kube-proxy为service后端的每个Pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod IP。该模式下kube-proxy不承担四层负责均衡器的角色,只负责创建iptables规则。该模式的优点是较userspace模式效率更高,但不能提供灵活的LB策略,当后端Pod不可用时也无法进行重试。
|
||||
|
||||
<img src="Service/image-20240912170931956.png" alt="image-20240912170931956" style="zoom:33%;" />
|
||||
|
||||
## ipvs模式
|
||||
|
||||
ipvs模式和iptables类似,kube-proxy监控Pod的变化并创建相应的ipvs规则。ipvs相对iptables转发效率更高。除此以外,ipvs支持更多的LB算法。
|
||||
|
||||
<img src="Service/image-20240912171043118.png" alt="image-20240912171043118" style="zoom:33%;" />
|
||||
|
||||
```yaml
|
||||
# 创建三个pod
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp-deploy
|
||||
name: myapp-deploy
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp-deploy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp-deploy
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
```bash
|
||||
# 启动一个负载均衡的service
|
||||
$ kubectl create svc clusterip myapp-deploy --tcp=80:80
|
||||
|
||||
# 修改ipvs
|
||||
$ kubectl edit configmap kube-proxy -n kube-system
|
||||
mode: "ipvs"
|
||||
|
||||
# 删除kube-proxy的pod
|
||||
$ kubectl delete pod -n kube-system -l k8s-app=kube-proxy
|
||||
pod "kube-proxy-ckwsj" deleted
|
||||
pod "kube-proxy-t729f" deleted
|
||||
pod "kube-proxy-z6dt8" deleted
|
||||
|
||||
# 查看pod创建的状态
|
||||
$ kubectl get pod -n kube-system -l k8s-app=kube-proxy
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
kube-proxy-948s5 1/1 Running 0 3s
|
||||
kube-proxy-ggpwj 1/1 Running 0 3s
|
||||
kube-proxy-v7lgs 1/1 Running 0 3s
|
||||
|
||||
# 查看虚拟IP地址
|
||||
$ kubectl get svc
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
myapp-deploy ClusterIP 10.9.86.78 <none> 80/TCP 6m54s
|
||||
|
||||
# 查看ipvsadm的状态
|
||||
$ ipvsadm -Ln
|
||||
IP Virtual Server version 1.2.1 (size=4096)
|
||||
Prot LocalAddress:Port Scheduler Flags
|
||||
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
|
||||
TCP 10.9.86.78:80 rr
|
||||
-> 10.244.140.106:80 Masq 1 0 0
|
||||
-> 10.244.196.141:80 Masq 1 0 0
|
||||
-> 10.244.196.142:80 Masq 1 0 0
|
||||
|
||||
# 负载均衡的地址正好对应着pod的ip地址
|
||||
$ kubectl get pod -o wide
|
||||
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS
|
||||
myapp-deploy-57bff895d5-b2hhk 1/1 Running 0 73s 10.244.196.142 node01 <none> <none>
|
||||
myapp-deploy-57bff895d5-fbln4 1/1 Running 0 73s 10.244.140.106 node02 <none> <none>
|
||||
myapp-deploy-57bff895d5-frnfd 1/1 Running 0 73s 10.244.196.141 node01 <none> <none>
|
||||
```
|
||||
|
||||
# Service资源清单
|
||||
|
||||
```yaml
|
||||
kind: Service # 资源类型
|
||||
apiVersion: v1 # 资源版本
|
||||
metadata: # 元数据
|
||||
name: service # 资源名称
|
||||
namespace: default # 命名空间
|
||||
spec: # 描述
|
||||
selector: # 标签选择器,用于确定当前service代理哪些pod
|
||||
app: nginx
|
||||
type: # Service类型,指定service的访问方式
|
||||
clusterIP: # 虚拟服务的ip地址
|
||||
sessionAffinity: # session亲和性,支持ClientIP、None两个选项
|
||||
sessionAffinityConfig:
|
||||
clientIP:
|
||||
timeoutSeconds: 120 # session的过期时间
|
||||
ports: # 端口信息
|
||||
- protocol: TCP
|
||||
port: 3017 # service端口
|
||||
targetPort: 5003 # pod端口
|
||||
nodePort: 31122 # 主机端口
|
||||
```
|
||||
|
||||
可以使用如下命令得到基本的yaml格式的文件
|
||||
|
||||
```bash
|
||||
$ kubectl create svc clusterip nginx --tcp=80:80 --dry-run=client -o yaml
|
||||
|
||||
$ ipvsadm -lnc
|
||||
```
|
||||
|
||||
`spec.type`可以选择的类型
|
||||
|
||||
- ClusterIP:默认值,它是Kubernetes系统自动分配的虚拟IP,只能在集群内部访问
|
||||
- NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务
|
||||
- LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境支持
|
||||
- ExternalName: 把集群外部的服务引入集群内部,直接使用
|
||||
|
||||
# Service使用
|
||||
|
||||
```yaml
|
||||
# 创建三个pod
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp-deploy
|
||||
name: myapp-deploy
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp-deploy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp-deploy
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
测试三个pod
|
||||
|
||||
```bash
|
||||
$ kubectl get pod -o wide
|
||||
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
|
||||
myapp-deploy-57bff895d5-b2hhk 1/1 Running 0 30m 10.244.196.142 node01 <none> <none>
|
||||
myapp-deploy-57bff895d5-fbln4 1/1 Running 0 30m 10.244.140.106 node02 <none> <none>
|
||||
myapp-deploy-57bff895d5-frnfd 1/1 Running 0 30m 10.244.196.141 node01 <none> <none>
|
||||
|
||||
# 查看一下访问情况
|
||||
$ curl 10.244.196.142/hostname.html
|
||||
myapp-deploy-57bff895d5-b2hhk
|
||||
$ curl 10.244.140.106/hostname.html
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
$ curl 10.244.196.141/hostname.html
|
||||
myapp-deploy-57bff895d5-frnfd
|
||||
```
|
||||
|
||||
## ClusterIP类型的Service
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-clusterip
|
||||
spec:
|
||||
selector:
|
||||
app: myapp-deploy
|
||||
# clusterIP: 172.16.66.66 # service的ip地址,如果不写,默认会生成一个
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80 # Service端口
|
||||
targetPort: 80 # pod端口
|
||||
```
|
||||
|
||||
查看运行结果
|
||||
|
||||
```bash
|
||||
$ kubectl get svc
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service-clusterip ClusterIP 10.13.125.29 <none> 80/TCP 22s
|
||||
|
||||
$ kubectl describe svc service-clusterip
|
||||
Name: service-clusterip
|
||||
Namespace: default
|
||||
Labels: <none>
|
||||
Annotations: <none>
|
||||
Selector: app=myapp-deploy
|
||||
Type: ClusterIP
|
||||
IP Family Policy: SingleStack
|
||||
IP Families: IPv4
|
||||
IP: 10.13.125.29
|
||||
IPs: 10.13.125.29
|
||||
Port: <unset> 80/TCP
|
||||
TargetPort: 80/TCP
|
||||
Endpoints: 10.244.140.106:80,10.244.196.141:80,10.244.196.142:80
|
||||
Session Affinity: None
|
||||
Events: <none>
|
||||
|
||||
$ ipvsadm -Ln
|
||||
IP Virtual Server version 1.2.1 (size=4096)
|
||||
Prot LocalAddress:Port Scheduler Flags
|
||||
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
|
||||
TCP 10.13.125.29:80 rr
|
||||
-> 10.244.140.106:80 Masq 1 0 0
|
||||
-> 10.244.196.141:80 Masq 1 0 0
|
||||
-> 10.244.196.142:80 Masq 1 0 0
|
||||
|
||||
$ while true;do curl 10.13.125.29/hostname.html; done
|
||||
myapp-deploy-57bff895d5-b2hhk
|
||||
myapp-deploy-57bff895d5-frnfd
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
myapp-deploy-57bff895d5-b2hhk
|
||||
myapp-deploy-57bff895d5-frnfd
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
```
|
||||
|
||||
## Endpoint
|
||||
|
||||
Endpoint是kubernetes中的一个资源对象,存储在etcd中,用来记录一个service对应的所有pod的访问地址,它是根据service配置文件中selector描述产生的。必须要满足就绪探测。
|
||||
|
||||
一个Service由一组Pod组成,这些Pod通过Endpoints暴露出来,**Endpoints是实现实际服务的端点集合**。换句话说,service和pod之间的联系是通过endpoints实现的。
|
||||
|
||||
<img src="Service/image-20240912172501813.png" alt="image-20240912172501813" style="zoom:33%;" />
|
||||
|
||||
```bash
|
||||
$ kubectl get endpoints -o wide
|
||||
NAME ENDPOINTS AGE
|
||||
service-clusterip 10.244.140.106:80,10.244.196.141:80,10.244.196.142:80 6m27s
|
||||
```
|
||||
|
||||
在deployment中添加一个就绪探测
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp-deploy
|
||||
name: myapp-deploy
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp-deploy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp-deploy
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 80
|
||||
path: /index1.html
|
||||
initialDelaySeconds: 1
|
||||
periodSeconds: 3
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
在不满足就绪探测的情况下,是不会被endpoint采用的
|
||||
|
||||
```bash
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
myapp-deploy-659f9975b8-2sntn 0/1 Running 0 40s
|
||||
myapp-deploy-659f9975b8-nd66b 0/1 Running 0 40s
|
||||
myapp-deploy-659f9975b8-p4j5k 0/1 Running 0 40s
|
||||
|
||||
$ kubectl get endpoints
|
||||
NAME ENDPOINTS AGE
|
||||
service-clusterip 10s
|
||||
```
|
||||
|
||||
满足了就绪探测和标签被匹配上的pod会被加入endpoint中
|
||||
|
||||
```bash
|
||||
$ kubectl exec -it myapp-deploy-659f9975b8-2sntn -- /bin/bash
|
||||
root@myapp-deploy-659f9975b8-2sntn:/# echo "hello world" > /usr/share/nginx/html/index1.html
|
||||
|
||||
$ kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
myapp-deploy-659f9975b8-2sntn 1/1 Running 0 3m4s
|
||||
myapp-deploy-659f9975b8-nd66b 0/1 Running 0 3m4s
|
||||
myapp-deploy-659f9975b8-p4j5k 0/1 Running 0 3m4s
|
||||
|
||||
$ kubectl get endpoints
|
||||
NAME ENDPOINTS AGE
|
||||
service-clusterip 10.244.140.107:80 3m1s
|
||||
|
||||
$ ipvsadm -L -n
|
||||
IP Virtual Server version 1.2.1 (size=4096)
|
||||
Prot LocalAddress:Port Scheduler Flags
|
||||
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
|
||||
TCP 10.12.150.224:80 rr
|
||||
-> 10.244.140.107:80 Masq 1 0 0
|
||||
```
|
||||
|
||||
**负载分发策略**
|
||||
|
||||
对Service的访问被分发到了后端的Pod上去,目前kubernetes提供了两种负载分发策略:
|
||||
|
||||
- 如果不定义,默认使用kube-proxy的策略,比如随机、轮询
|
||||
|
||||
- 基于客户端地址的会话保持模式,即来自同一个客户端发起的所有请求都会转发到固定的一个Pod上
|
||||
|
||||
此模式可以使在spec中添加`sessionAffinity: ClientIP`选项
|
||||
|
||||
```bash
|
||||
$ kubectl edit svc service-clusterip
|
||||
sessionAffinity: ClientIP
|
||||
|
||||
$ while true;do curl 10.13.125.29/hostname.html; done
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
myapp-deploy-57bff895d5-fbln4
|
||||
|
||||
$ ipvsadm -Ln
|
||||
IP Virtual Server version 1.2.1 (size=4096)
|
||||
Prot LocalAddress:Port Scheduler Flags
|
||||
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
|
||||
TCP 10.13.125.29:80 rr persistent 10800
|
||||
-> 10.244.140.106:80 Masq 1 0 155
|
||||
-> 10.244.196.141:80 Masq 1 0 0
|
||||
-> 10.244.196.142:80 Masq 1 0 0
|
||||
```
|
||||
|
||||
## HeadLess类型的Service
|
||||
|
||||
在某些场景中,开发人员可能不想使用Service提供的负载均衡功能,而希望自己来控制负载均衡策略,针对这种情况,kubernetes提供了HeadLiness Service,这类Service不会分配Cluster IP,如果想要访问service,只能通过service的域名进行查询。
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-headliness
|
||||
spec:
|
||||
selector:
|
||||
app: myapp-deploy
|
||||
clusterIP: None # 将clusterIP设置为None,即可创建headliness Service
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
```
|
||||
|
||||
```bash
|
||||
$ kubectl get svc -o wide
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
|
||||
service-headliness ClusterIP None <none> 80/TCP 40s app=myapp-deploy
|
||||
|
||||
$ kubectl describe svc service-headliness
|
||||
Name: service-headliness
|
||||
Namespace: default
|
||||
Labels: <none>
|
||||
Annotations: <none>
|
||||
Selector: app=myapp-deploy
|
||||
Type: ClusterIP
|
||||
IP Family Policy: SingleStack
|
||||
IP Families: IPv4
|
||||
IP: None
|
||||
IPs: None
|
||||
Port: <unset> 80/TCP
|
||||
TargetPort: 80/TCP
|
||||
Endpoints: 10.244.140.107:80
|
||||
Session Affinity: None
|
||||
Events: <none>
|
||||
|
||||
$ kubectl exec -it myapp-deploy-659f9975b8-2sntn -- /bin/bash
|
||||
root@myapp-deploy-659f9975b8-2sntn:/# cat /etc/resolv.conf
|
||||
nameserver 10.0.0.10
|
||||
search default.svc.cluster.local svc.cluster.local cluster.local
|
||||
options ndots:5
|
||||
|
||||
$ dig @10.0.0.10 service-headliness.default.svc.cluster.local
|
||||
;; ANSWER SECTION:
|
||||
service-headliness.default.svc.cluster.local. 30 IN A 10.244.140.107
|
||||
service-headliness.default.svc.cluster.local. 30 IN A 10.244.196.145
|
||||
service-headliness.default.svc.cluster.local. 30 IN A 10.244.196.144
|
||||
```
|
||||
|
||||
## NodePort类型的Service
|
||||
|
||||
在之前的样例中,创建的Service的ip地址只有集群内部才可以访问,如果希望将Service暴露给集群外部使用,那么就要使用到另外一种类型的Service,称为NodePort类型。NodePort的工作原理其实就是**将service的端口映射到Node的一个端口上**,然后就可以通过`NodeIp:NodePort`来访问service了。
|
||||
|
||||
<img src="Service/image-20240913143156247.png" alt="image-20240913143156247" style="zoom:33%;" />
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-nodeport
|
||||
spec:
|
||||
selector:
|
||||
app: myapp-deploy
|
||||
type: NodePort # service类型
|
||||
ports:
|
||||
- port: 80
|
||||
nodePort: 30002 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配
|
||||
targetPort: 80
|
||||
```
|
||||
|
||||
查看是否能够正常的访问
|
||||
|
||||
```bash
|
||||
$ for i in {1..6};do curl 192.168.173.100:30002/hostname.html;done
|
||||
myapp-deploy-659f9975b8-nd66b
|
||||
myapp-deploy-659f9975b8-p4j5k
|
||||
myapp-deploy-659f9975b8-2sntn
|
||||
myapp-deploy-659f9975b8-nd66b
|
||||
myapp-deploy-659f9975b8-p4j5k
|
||||
myapp-deploy-659f9975b8-2sntn
|
||||
```
|
||||
|
||||
## LoadBalancer类型的Service
|
||||
|
||||
LoadBalancer和NodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。
|
||||
|
||||

|
||||
|
||||
## ExternalName类型的Service
|
||||
|
||||
ExternalName类型的Service用于引入集群外部的服务,它通过`externalName`属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。
|
||||
|
||||
<img src="Service/image-20240913160143805.png" alt="image-20240913160143805" style="zoom:33%;" />
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service-externalname
|
||||
namespace: dev
|
||||
spec:
|
||||
type: ExternalName # service类型
|
||||
externalName: www.baidu.com #改成ip地址也可以
|
||||
```
|
||||
|
||||
```bash
|
||||
$ kubectl get svc
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service-externalname ExternalName <none> www.baidu.com <none> 7s
|
||||
|
||||
$ dig @10.0.0.10 service-externalname.default.svc.cluster.local
|
||||
;; ANSWER SECTION:
|
||||
service-externalname.default.svc.cluster.local. 30 IN CNAME www.baidu.com.
|
||||
www.baidu.com. 30 IN CNAME www.a.shifen.com.
|
||||
www.a.shifen.com. 30 IN A 180.101.50.242
|
||||
www.a.shifen.com. 30 IN A 180.101.50.188
|
||||
```
|
||||
|
||||
# Ingress介绍
|
||||
|
||||
在前面课程中已经提到,Service对集群之外暴露服务的主要方式有两种:NotePort和LoadBalancer,但是这两种方式,都有一定的缺点:
|
||||
|
||||
- NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显
|
||||
- LB方式的缺点是每个service需要一个LB,浪费、麻烦,并且需要kubernetes之外设备的支持
|
||||
|
||||
基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。工作机制大致如下图表示:
|
||||
|
||||
<img src="Service/image-20240913161756342.png" alt="image-20240913161756342" style="zoom:33%;" />
|
||||
|
||||
实际上,Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在**Ingress里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务**。在这里有两个核心概念:
|
||||
|
||||
- ingress:kubernetes中的一个对象,作用是定义请求如何转发到service的规则
|
||||
- ingress controller:具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现方式有很多,比如Nginx, Contour, Haproxy等等
|
||||
|
||||
Ingress(以Nginx为例)的工作原理如下:
|
||||
|
||||
1. 用户编写Ingress规则,说明哪个域名对应kubernetes集群中的哪个Service
|
||||
2. Ingress控制器动态感知Ingress服务规则的变化,然后生成一段对应的Nginx反向代理配置
|
||||
3. Ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新
|
||||
4. 到此为止,其实真正在工作的就是一个Nginx了,内部配置了用户定义的请求转发规则
|
||||
|
||||
<img src="Service/image-20240914142642245.png" alt="image-20240914142642245" style="zoom:33%;" />
|
||||
|
||||
## 安装helm
|
||||
|
||||
```bash
|
||||
# 安装helm,helm在kubernetes中相当于yum,是可以在线去获取资源清单,快速部署服务
|
||||
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
|
||||
$ chmod 700 get_helm.sh
|
||||
$ ./get_helm.sh
|
||||
|
||||
# 初始化,可以从 https://artifacthub.io/ 中选择一个可用的仓库地址
|
||||
$ helm repo add bitnami https://charts.bitnami.com/bitnami
|
||||
$ helm repo list
|
||||
NAME URL
|
||||
bitnami https://charts.bitnami.com/bitnami
|
||||
|
||||
# 常见操作
|
||||
$ helm repo update # 更新chart列表
|
||||
$ helm show chart bitnami/apache # 查看chart基本信息
|
||||
$ helm install bitnami/apache --generate-name # 部署chart
|
||||
$ helm list # 查看部署包,加上--all可以看到所有的
|
||||
$ helm uninstall apache-1726297430 # 删除这个安装包所有的kubernetes资源
|
||||
|
||||
$ helm search hub wordpress # 在 helm hub(https://hub.helm.sh)上搜索helm chart
|
||||
$ helm search repo wordpress # 在repo中搜索
|
||||
```
|
||||
|
||||
## 安装Ingress-nginx
|
||||
|
||||
```bash
|
||||
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
|
||||
$ helm pull ingress-nginx/ingress-nginx
|
||||
|
||||
# 修改 values.yaml 文件
|
||||
修改 hostNetwork 的值为 true
|
||||
dnsPolicy的值改为: ClusterFirstWithHostNet
|
||||
kind类型更改为:DaemonSet
|
||||
ingressClassResource.default:true
|
||||
|
||||
# 关闭所有镜像的 digest
|
||||
|
||||
# 如果是本地的helm chart,使用这个命令安装
|
||||
$ kubectl create ns ingress
|
||||
$ helm install ingress-nginx -n ingress . -f values.yaml
|
||||
$ kubectl get pod -n ingress
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
ingress-nginx-controller-7c4x8 1/1 Running 0 12s
|
||||
ingress-nginx-controller-bjk4s 1/1 Running 0 12s
|
||||
```
|
||||
|
||||
## 实验测试
|
||||
|
||||
创建如下两个资源模型
|
||||
|
||||

|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: aaronxudocker/myapp:v1.0
|
||||
ports:
|
||||
- containerPort: 80
|
||||
|
||||
---
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: tomcat-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tomcat
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tomcat
|
||||
spec:
|
||||
containers:
|
||||
- name: tomcat
|
||||
image: tomcat:8.5-jre10-slim
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-service
|
||||
spec:
|
||||
selector:
|
||||
app: nginx
|
||||
clusterIP: None
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: tomcat-service
|
||||
spec:
|
||||
selector:
|
||||
app: tomcat
|
||||
clusterIP: None
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
```
|
||||
|
||||
### Http代理
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ingress-nginx
|
||||
spec:
|
||||
rules:
|
||||
- host: nginx.iproute.cn
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-service
|
||||
port:
|
||||
number: 80
|
||||
ingressClassName: nginx
|
||||
---
|
||||
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ingress-tomcat
|
||||
spec:
|
||||
rules:
|
||||
- host: tomcat.iproute.cn
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: tomcat-service
|
||||
port:
|
||||
number: 8080
|
||||
ingressClassName: nginx
|
||||
```
|
||||
|
||||
查看运行状态
|
||||
|
||||
```bash
|
||||
$ kubectl get ing
|
||||
NAME CLASS HOSTS ADDRESS PORTS AGE
|
||||
ingress-nginx nginx nginx.iproute.cn 80 7s
|
||||
ingress-tomcat nginx tomcat.iproute.cn 80 7s
|
||||
|
||||
$ kubectl describe ing
|
||||
|
||||
Rules:
|
||||
Host Path Backends
|
||||
---- ---- --------
|
||||
nginx.iproute.cn
|
||||
/ nginx-service:80 (10.244.140.109:80,10.244.196.149:80,10.244.196.150:80)
|
||||
|
||||
Rules:
|
||||
Host Path Backends
|
||||
---- ---- --------
|
||||
tomcat.iproute.cn
|
||||
/ tomcat-service:8080 (10.244.140.110:8080,10.244.196.151:8080,10.244.196.153:8080)
|
||||
```
|
||||
|
||||
访问测试
|
||||
|
||||

|
||||
|
||||
其中nginx多次访问主机名,可以看到负载均衡
|
||||
|
||||

|
||||
|
||||
## Https代理
|
||||
|
||||
创建证书
|
||||
|
||||
```bash
|
||||
# 生成证书
|
||||
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=iproute.cn"
|
||||
|
||||
# 创建密钥
|
||||
$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt
|
||||
```
|
||||
|
||||
创建资源清单
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: https-nginx
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- nginx.iproute.cn
|
||||
secretName: tls-secret # 指定秘钥
|
||||
rules:
|
||||
- host: nginx.iproute.cn
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nginx-service
|
||||
port:
|
||||
number: 80
|
||||
ingressClassName: nginx
|
||||
---
|
||||
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: tomcat-https
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- tomcat.iproute.cn
|
||||
secretName: tls-secret # 指定秘钥
|
||||
rules:
|
||||
- host: tomcat.iproute.cn
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: tomcat-service
|
||||
port:
|
||||
number: 8080
|
||||
ingressClassName: nginx
|
||||
```
|
||||
|
||||
访问测试
|
||||
|
||||

|
||||
|
||||
可以看到负载均衡
|
||||
|
||||

|
BIN
Kubernetes/Service/image-20240912140110844.png
Normal file
After Width: | Height: | Size: 193 KiB |
BIN
Kubernetes/Service/image-20240912152844652.png
Normal file
After Width: | Height: | Size: 156 KiB |
BIN
Kubernetes/Service/image-20240912170627727.png
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
Kubernetes/Service/image-20240912170931956.png
Normal file
After Width: | Height: | Size: 186 KiB |
BIN
Kubernetes/Service/image-20240912171043118.png
Normal file
After Width: | Height: | Size: 181 KiB |
BIN
Kubernetes/Service/image-20240912172501813.png
Normal file
After Width: | Height: | Size: 177 KiB |
BIN
Kubernetes/Service/image-20240913143156247.png
Normal file
After Width: | Height: | Size: 577 KiB |
BIN
Kubernetes/Service/image-20240913145934612.png
Normal file
After Width: | Height: | Size: 2.1 MiB |
BIN
Kubernetes/Service/image-20240913154405309.png
Normal file
After Width: | Height: | Size: 210 KiB |
BIN
Kubernetes/Service/image-20240913160143805.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
Kubernetes/Service/image-20240913161756342.png
Normal file
After Width: | Height: | Size: 448 KiB |
BIN
Kubernetes/Service/image-20240914142642245.png
Normal file
After Width: | Height: | Size: 280 KiB |
BIN
Kubernetes/Service/image-20240914152836257.png
Normal file
After Width: | Height: | Size: 239 KiB |
BIN
Kubernetes/Service/image-20240914154740672.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
Kubernetes/Service/image-20240914154758983.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
Kubernetes/Service/image-20240914155615236.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
Kubernetes/Service/image-20240914155628119.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
Kubernetes/kubernetes概述/IAAS.png
Normal file
After Width: | Height: | Size: 179 KiB |
BIN
Kubernetes/kubernetes概述/PAAS.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
Kubernetes/kubernetes概述/kubernetes优势.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
Kubernetes/kubernetes概述/kubernetes现状.png
Normal file
After Width: | Height: | Size: 97 KiB |
BIN
Kubernetes/kubernetes概述/kubernetes集群组件-2.png
Normal file
After Width: | Height: | Size: 95 KiB |
BIN
Kubernetes/kubernetes概述/kubernetes集群组件.png
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
Kubernetes/kubernetes概述/云原生演变.png
Normal file
After Width: | Height: | Size: 147 KiB |
BIN
Kubernetes/pod与网络/image-20240904112128424.png
Normal file
After Width: | Height: | Size: 492 KiB |
BIN
Kubernetes/pod与网络/image-20240904112421964.png
Normal file
After Width: | Height: | Size: 119 KiB |
BIN
Kubernetes/pod与网络/image-20240904115715394.png
Normal file
After Width: | Height: | Size: 985 KiB |
BIN
Kubernetes/pod与网络/image-20240904134937631.png
Normal file
After Width: | Height: | Size: 236 KiB |
BIN
Kubernetes/pod与网络/image-20240904135319098.png
Normal file
After Width: | Height: | Size: 310 KiB |
BIN
Kubernetes/pod与网络/image-20240904135633230.png
Normal file
After Width: | Height: | Size: 300 KiB |
BIN
Kubernetes/pod与网络/image-20240904135815763.png
Normal file
After Width: | Height: | Size: 290 KiB |
BIN
Kubernetes/pod与网络/image-20240904140729187.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
Kubernetes/pod与网络/image-20240904140805520.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
Kubernetes/pod与网络/image-20240904141203196.png
Normal file
After Width: | Height: | Size: 237 KiB |
BIN
Kubernetes/pod与网络/image-20240904142345171.png
Normal file
After Width: | Height: | Size: 292 KiB |
BIN
Kubernetes/pod与网络/image-20240904143234102.png
Normal file
After Width: | Height: | Size: 440 KiB |
BIN
Kubernetes/pod与网络/image-20240904145716982.png
Normal file
After Width: | Height: | Size: 291 KiB |