├── .DS_Store ├── .gitignore ├── Docker开源书.pdf ├── Kubernetes开源书.pdf ├── README.md ├── docker ├── .DS_Store ├── README.md ├── SUMMARY.md ├── book.json ├── 第1章-Docker入门 │ ├── 00-准备工作.md │ ├── 01-Docker简介.md │ ├── 02-Docker安装.md │ ├── 03-配置镜像加速器.md │ ├── 04-镜像常用命令.md │ ├── 05-容器常用命令.md │ ├── 06-实战:修改Nginx首页.md │ ├── 07-复习.md │ └── images │ │ ├── 12-1.png │ │ ├── 12-3.png │ │ ├── 13-2.png │ │ ├── 13-3.png │ │ ├── docker-registry.jpg │ │ ├── docker-vs-vm.png │ │ ├── nexus.png │ │ └── 镜像加速器.png ├── 第2章-Dockerfile详解 │ ├── 08-1-Dockerfile最佳实践.md │ ├── 08-Dockerfile指令详解.md │ ├── 09-实战:使用Dockerfile修改Nginx首页.md │ ├── 10-实战:使用Dockerfile在CentOS 7中安装Nginx.md │ ├── 11-实战:使用Dockerfile构建一个Spring Boot应用镜像.md │ ├── 12-实战:巩固-阅读常用软件的Dockerfile.md │ └── images │ │ ├── 12-1.png │ │ ├── 13-2.png │ │ ├── 13-3.png │ │ ├── docker-registry.jpg │ │ ├── docker-vs-vm.png │ │ ├── docker-版本迭代计划.png │ │ ├── nexus.png │ │ └── 镜像加速器.png ├── 第3章-Docker镜像管理 │ ├── 13-使用Docker Hub管理镜像.md │ ├── 14-使用Docker Registry管理Docker镜像.md │ ├── 15-使用Nexus管理Docker镜像.md │ └── images │ │ ├── 12-1.png │ │ ├── 13-2.png │ │ ├── 13-3.png │ │ ├── docker-registry.jpg │ │ ├── docker-vs-vm.png │ │ ├── docker-版本迭代计划.png │ │ ├── nexus.png │ │ └── 镜像加速器.png ├── 第4章-Docker工具 │ ├── 16-使用Maven插件构建Docker镜像.md │ ├── 17-小作业.md │ ├── 18-Docker可视化管理工具.md │ └── images │ │ ├── 12-1.png │ │ ├── 13-2.png │ │ ├── 13-3.png │ │ ├── docker-registry.jpg │ │ ├── docker-vs-vm.png │ │ ├── docker-版本迭代计划.png │ │ ├── nexus.png │ │ └── 镜像加速器.png ├── 第5章-Docker数据持久化 │ ├── 19-Docker数据持久化.md │ └── images │ │ ├── 12-1.png │ │ ├── 13-2.png │ │ ├── 13-3.png │ │ ├── docker-registry.jpg │ │ ├── docker-vs-vm.png │ │ ├── docker-版本迭代计划.png │ │ ├── nexus.png │ │ └── 镜像加速器.png ├── 第6章-Docker网络 │ ├── 20-端口映射.md │ ├── 21-遗留网络.md │ ├── 22-Docker网络.md │ ├── 23-network命令.md │ ├── 24-默认bridge网络中配置DNS.md │ ├── 25-用户定义网络中的内嵌DNS服务器.md │ └── images │ │ ├── bridge_network.png │ │ ├── network_access.png │ │ └── working.png └── 第7章-Docker Compose │ ├── 26-Docker Compose简介.md │ ├── 27-安装Docker Compose.md │ ├── 28-Docker Compose快速入门.md │ ├── 29-docker-compose.yml常用命令.md │ ├── 30-docker-compose常用命令.md │ ├── 31-Docker Compose网络设置.md │ ├── 32-小练习:使用Docker Compose编排WordPress博客.md │ ├── 33-控制服务启动顺序.md │ ├── 34-在生产环境中使用Docker Compose.md │ ├── 35-实战:使用Docker Compose运行ELK.md │ ├── 36-使用Docker Compose伸缩应用.md │ ├── images │ ├── 14-1.png │ ├── 14-2.png │ └── 14-3.png │ └── wait-for-it-master.zip └── kubernetes ├── .DS_Store ├── 01-Overview ├── K8s组件.md ├── Kubernetes API.md ├── Working with Kubernetes Objects │ ├── Annotation.md │ ├── Label和Selector.md │ ├── Name.md │ ├── Namespace.md │ └── 理解K8s对象.md ├── images │ └── why_containers.svg └── 什么是K8s.md ├── 02-Kubernetes Architecture ├── .DS_Store ├── K8s架构及基本概念.md ├── Master与Node的通信.md ├── Node.md └── images │ ├── horizontal-pod-autoscaler.svg │ ├── k8s-architecture.png │ ├── kubernetes-install.png │ └── service-pod.png ├── 05-Workloads ├── Controllers │ ├── .DS_Store │ ├── Daemon Set.md │ ├── Deployment.md │ ├── Replica Set.md │ └── StatefulSet.md └── Pods │ ├── .DS_Store │ ├── Pod.md │ └── images │ ├── pod.svg │ └── pod2.svg ├── 06-Configuration ├── Assigning Pods to Nodes.md ├── Configuration Best Practices.md ├── Managing Compute Resources for Containers.md ├── Pod Priority and Preemption.md ├── Secrets.md └── Taints and Tolerations.md ├── 07-Services, Load Balancing, and Networking ├── Ingress Resources.md ├── Service.md └── images │ ├── services-iptables-overview.svg │ └── services-userspace-overview.svg ├── 100-其他 ├── .DS_Store ├── Horizontal Pod Autoscaling.md ├── K8s资源分配.md ├── images │ ├── horizontal-pod-autoscaler.svg │ ├── hpa.png │ ├── k8s-architecture.png │ ├── kubernetes-install.png │ └── service-pod.png └── 实战:使用K8s编排Wordpress博客.md ├── 99-安装 ├── .DS_Store ├── 01-安装单机版Kubernetes.md ├── 02-使用Kubespray部署生产可用的Kubernetes集群(1.11.2).md └── images │ └── kubernetes-install.png ├── README.md ├── SUMMARY.md └── book.json /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | target/ 3 | 4 | 5 | # Eclipse project files 6 | .classpath 7 | .project 8 | .settings 9 | 10 | # IDEA metadata and output dirs 11 | *.iml 12 | *.ipr 13 | *.iws 14 | .idea/ 15 | 16 | # gitbook 17 | _book 18 | tmp 19 | .springBeans -------------------------------------------------------------------------------- /Docker开源书.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/Docker开源书.pdf -------------------------------------------------------------------------------- /Kubernetes开源书.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/Kubernetes开源书.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker与Kubernetes开源书 2 | 3 | * Gitee: 4 | * GitHub: 5 | 6 | 之前写的《Spring Cloud开源书》,有兴趣的可详见: 7 | 8 | * Gitee: 9 | * GitHub: 10 | 11 | 12 | 欢迎star、fork,一起讨论! 13 | 14 | * QQ群:731548893 15 | * 微信群:加jumping_me,注明加群。 16 | 17 | 18 | 本开源书,包含两部分: 19 | 20 | ## Docker 21 | 22 | Docker部分,包括: 23 | 24 | * 入门 25 | * Dockerfile详解 26 | * 镜像管理 27 | * 工具 28 | * 持久化 29 | * 网络 30 | * Docker Compose 31 | 32 | 七大主题,涵盖Docker常用命令、Dockerfile常用命令、网络、存储、Docker Compose等常见知识点,知识体系应该是比较完备的。如果学习完,你应该具备如下能力: 33 | 34 | * 常用的命令信手拈来 35 | * Dockerfile编写无压力 36 | * 能用Docker Compose快速构建容器环境 37 | * 理解Docker网络、存储等知识点是怎么回事。 38 | 39 | 详见`docker`目录。 40 | 41 | 42 | 43 | ## Kubernetes 44 | 45 | Kubernetes部分,是个人学习Kubernetes时,对官方文档的翻译。在官方翻译的基础上,结合自己的理解,做了一些批注。 46 | 47 | 由于是SOLO翻译,精力有限,无法翻译全部文档,而且翻译本身也是为自己学习服务的,不是闲的蛋疼翻译玩,又或者有什么功利心。从知识体系上来看,可能不是那么的完备……不过其实常见的知识点在我的文档里也都包含了。 48 | 49 | 详见`kubernetes`目录。 50 | 51 | > TIPS:就翻译质量来看,吹个牛,似乎目前还没有找到比我这个更好的。 52 | 53 | 54 | 55 | ## 如何使用 56 | 57 | - 方法一、懒人用法:直接下载根目录的`Docker开源书.pdf` 、`Kubernetes开源书.pdf` 阅读; 58 | - 方法二、将代码clone到本地后,使用Typora或Atom等Markdown阅读软件进行阅读; 59 | - 方法三、前往 阅读 60 | 61 | 62 | 63 | ENJOY IT! 64 | 65 | 66 | 67 | ## 广告时间 68 | 69 | * 个人博客: 70 | * 个人微信:`jumping_me` 71 | * ![](ad.png) -------------------------------------------------------------------------------- /docker/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/.DS_Store -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # Docker开源书 2 | 3 | Docker开源书,旨在帮助大家熟悉Docker、使用Docker。 4 | 5 | > * GitHub地址: 6 | > * Gitee地址: 7 | > 8 | > 欢迎star、fork,一起讨论! 9 | > 10 | > QQ群:731548893 11 | > 12 | > 微信群:加jumping_me,注明加群。 13 | 14 | 内容主要包括: 15 | 16 | - 入门 17 | - Dockerfile详解 18 | - 镜像管理 19 | - 工具 20 | - 持久化 21 | - 网络 22 | - Docker Compose 23 | 24 | 七大主题,涵盖Docker常用命令、Dockerfile常用命令、网络、存储、Docker Compose等常见知识点,知识体系应该是比较完备的。如果学习完,你应该具备如下能力: 25 | 26 | - 常用的命令信手拈来 27 | - Dockerfile编写无压力 28 | - 能用Docker Compose快速构建容器环境 29 | - 理解Docker网络、存储等知识点是怎么回事。 -------------------------------------------------------------------------------- /docker/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [简介](README.md) 4 | * [01-Docker简介](第1章-Docker入门/01-Docker简介.md) 5 | * [02-Docker安装](第1章-Docker入门/02-Docker安装.md) 6 | * [03-配置镜像加速器](第1章-Docker入门/03-配置镜像加速器.md) 7 | * [04-镜像常用命令](第1章-Docker入门/04-镜像常用命令.md) 8 | * [05-容器常用命令](第1章-Docker入门/05-容器常用命令.md) 9 | * [06-实战:修改Nginx首页](第1章-Docker入门/06-实战:修改Nginx首页.md) 10 | * [07-Dockerfile指令详解](第2章-Dockerfile详解/08-Dockerfile指令详解.md) 11 | * [08-实战:使用Dockerfile修改Nginx首页](第2章-Dockerfile详解/09-实战:使用Dockerfile修改Nginx首页.md) 12 | * [09-实战:巩固-阅读常用软件的Dockerfile](第2章-Dockerfile详解/12-实战:巩固-阅读常用软件的Dockerfile.md) 13 | * [10-使用Docker Hub管理镜像](第3章-Docker镜像管理/13-使用Docker Hub管理镜像.md) 14 | * [11-使用Docker Registry管理Docker镜像](第3章-Docker镜像管理/14-使用Docker Registry管理Docker镜像.md) 15 | * [12-使用Nexus管理Docker镜像](第3章-Docker镜像管理/15-使用Nexus管理Docker镜像.md) 16 | * [13-Docker可视化管理工具](第4章-Docker工具/18-Docker可视化管理工具.md) 17 | * [14-Docker数据持久化](第5章-Docker数据持久化/19-Docker数据持久化.md) 18 | * [15-端口映射](第6章-Docker网络/20-端口映射.md) 19 | * [16-遗留网络](第6章-Docker网络/21-遗留网络.md) 20 | * [17-Docker网络](第6章-Docker网络/22-Docker网络.md) 21 | * [18-network命令](第6章-Docker网络/23-network命令.md) 22 | * [19-默认bridge网络中配置DNS](第6章-Docker网络/24-默认bridge网络中配置DNS.md) 23 | * [20-用户定义网络中的内嵌DNS服务器](第6章-Docker网络/25-用户定义网络中的内嵌DNS服务器.md) 24 | * [21-Docker Compose简介](第7章-Docker Compose/26-Docker Compose简介.md) 25 | * [22-安装Docker Compose](第7章-Docker Compose/27-安装Docker Compose.md) 26 | * [23-Docker Compose快速入门](第7章-Docker Compose/28-Docker Compose快速入门.md) 27 | * [24-docker-compose.yml常用命令](第7章-Docker Compose/29-docker-compose.yml常用命令.md) 28 | * [25-docker-compose常用命令](第7章-Docker Compose/30-docker-compose常用命令.md) 29 | * [26-Docker Compose网络设置](第7章-Docker Compose/31-Docker Compose网络设置.md) 30 | * [27-实战:使用Docker Compose编排WordPress博客](第7章-Docker Compose/32-小练习:使用Docker Compose编排WordPress博客.md) 31 | * [28-控制服务启动顺序](第7章-Docker Compose/33-控制服务启动顺序.md) 32 | * [29-在生产环境中使用Docker Compose](第7章-Docker Compose/34-在生产环境中使用Docker Compose.md) 33 | * [30-实战:使用Docker Compose运行ELK](第7章-Docker Compose/35-实战:使用Docker Compose运行ELK.md) 34 | * [31-使用Docker Compose伸缩应用](第7章-Docker Compose/36-使用Docker Compose伸缩应用.md) 35 | 36 | -------------------------------------------------------------------------------- /docker/book.json: -------------------------------------------------------------------------------- 1 | { 2 | "title" : "Docker实战", 3 | "description" : "实战Docker", 4 | "author" : "周立", 5 | "links": { 6 | "sidebar" : { 7 | "博客": "http://www.itmuch.com" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /docker/第1章-Docker入门/00-准备工作.md: -------------------------------------------------------------------------------- 1 | # 第〇章 准备工作 2 | 3 | 尽管Docker在Windows 10、macOS、各种Linux系统中都可以很好地运行,但不得不说,不同系统中Docker的体验是有一定区别的。例如macOS中,没有docker0网桥,compose每个容器都必须暴露端口等。 4 | 5 | 因此,为了体验的一致性,以及规避很多不必要的问题,笔者将使用CentOS 7进行教学。**强烈建议大家安装好CentOS 7并在其中安装Docker。** 6 | 7 | * 参考材料《第二章 Docker安装》的说明安装即可。 8 | 9 | 10 | -------------------------------------------------------------------------------- /docker/第1章-Docker入门/01-Docker简介.md: -------------------------------------------------------------------------------- 1 | # Docker简介 2 | 3 | ## 1.1 Docker简介 4 | 5 | Docker是一个开源的**容器引擎**,它可以帮助我们更快地交付应用。Docker可将应用程序和基础设施层隔离,并且能将基础设施当作程序一样进行管理。使用Docker,可更快地打包、测试以及部署应用程序,并可**减少从编写到部署运行代码的周期**。 6 | 7 | **TIPS** 8 | 9 | (1) Docker官方网站: 10 | 11 | (2) Docker GitHub: 12 | 13 | 14 | 15 | ## 1.2 版本与迭代计划 16 | 17 | 近日,Docker发布了Docker 17.06。进入Docker 17时代后,Docker分成了两个版本:Docker EE和Docker CE,即:企业版(EE)和社区版(CE)。 18 | 19 | ### 1.2.1 版本区别 20 | 21 | **Docker EE**(企业版) 22 | 23 | Docker EE由公司支持,可在经过认证的操作系统和云提供商中使用,并可运行来自Docker Store的、经过认证的容器和插件。 24 | 25 | Docker EE提供三个服务层次: 26 | 27 | | 服务层级 | 功能 | 28 | | -------- | ---------------------------------------- | 29 | | Basic | 包含用于认证基础设施的Docker平台
Docker公司的支持
经过 认证的、来自Docker Store的容器与插件 | 30 | | Standard | 添加高级镜像与容器管理
LDAP/AD用户集成
基于角色的访问控制(Docker Datacenter) | 31 | | Advanced | 添加Docker安全扫描
连续漏洞监控 | 32 | 33 | 大家可在该页查看各个服务层次的价目: 。 34 | 35 | **Docker CE** 36 | 37 | Docker CE是免费的Docker产品的新名称,Docker CE包含了完整的Docker平台,非常适合开发人员和运维团队构建容器APP。事实上,Docker CE 17.03,可理解为Docker 1.13.1的Bug修复版本。因此,从Docker 1.13升级到Docker CE 17.03风险相对是较小的。 38 | 39 | 大家可前往Docker的RELEASE log查看详情 。 40 | 41 | Docker公司认为,Docker CE和EE版本的推出为Docker的生命周期、可维护性以及可升级性带来了巨大的改进。 42 | 43 | ### 1.2.2 版本迭代计划 44 | 45 | Docker从17.03开始,转向基于时间的`YY.MM` 形式的版本控制方案,类似于Canonical为Ubuntu所使用的版本控制方案。 46 | 47 | Docker CE有两种版本: 48 | 49 | edge版本每月发布一次,主要面向那些喜欢尝试新功能的用户。 50 | 51 | stable版本每季度发布一次,适用于希望更加容易维护的用户(稳定版)。 52 | 53 | edge版本只能在当前月份获得安全和错误修复。而stable版本在初始发布后四个月内接收关键错误修复和安全问题的修补程序。这样,Docker CE用户就有一个月的窗口期来切换版本到更新的版本。举个例子,Docker CE 17.03会维护到17年07月;而Docker CE 17.03的下个稳定版本是CE 17.06,这样,6-7月这个时间窗口,用户就可以用来切换版本了。 54 | 55 | Docker EE和stable版本的版本号保持一致,每个Docker EE版本都享受**为期一年**的支持与维护期,在此期间接受安全与关键修正。 56 | 57 | ![Docker版本演进图](images/docker-版本迭代计划.png) 58 | 59 | 60 | 61 | ### 1.2.3 参考文档 62 | 63 | ANNOUNCING DOCKER ENTERPRISE EDITION: 64 | 65 | 66 | 67 | ## 1.3 Docker的发展历程 68 | 69 | * 发展历程 70 | 71 | | Docker版本 | Docker基于{}实现 | 72 | | ---------------- | --------------------- | 73 | | Docker 0.7之前 | 基于LXC | 74 | | Docker0.9后 | 改用libcontainer | 75 | | **Docker 1.11后** | **改用runC和containerd** | 76 | 77 | * 表格名词对应官网 78 | * LXC: 79 | * libcontainer: 80 | * runC: 81 | * containerd: 82 | * 各名词之间的关系 83 | * [OCI](https://www.opencontainers.org/):定义了容器运行的标准,该标准目前由[libcontainer](https://github.com/docker/libcontainer)和[appc](https://github.com/appc/spec)的项目负责人(maintainer)进行维护和制定,其规范文档作为一个项目在GitHub上维护。 84 | * runC(标准化容器执行引擎):根据根据OCI规范编写的,生成和运行容器的CLI工具,是按照开放容器格式标准(OCF, Open Container Format)制定的一种具体实现。由libcontainer中迁移而来的,实现了容器启停、资源隔离等功能。 85 | * containerd:用于控制runC的守护进程,构建在OCI规范和runC之上。目前內建在Docker Engine中,参考文档: ,译文: 86 | * 浅谈发展历程 87 | - 时序:Docker大受欢迎 - 与CoreOS相爱相杀 - rkt诞生 - 各大厂商不爽 - OCI制定(2015-06) - 成立CNCF(2015-07-21) - Kubernetes 1.0发布; 88 | - [CNCF](http://cncf.io):云原生计算基金会,由谷歌联合发起,现隶属于Linux基金会。 89 | * 拓展阅读 90 | * Docker背后的标准化容器执行引擎——runC: 91 | * Docker、Containerd、RunC...:你应该知道的所有: 92 | * Google宣布成立CNCF基金会,Kubernetes 1.0正式发布: 93 | 94 | 95 | 96 | 97 | 98 | ## 1.4 Docker快速入门 99 | 100 | 执行如下命令,即可启动一个Nginx容器 101 | 102 | ```shell 103 | docker run -d -p 91:80 nginx 104 | ``` 105 | 106 | 107 | 108 | ## 1.5 Docker架构 109 | 110 | 我们来看一下来自Docker官方文档的架构图,如图12-1所示。 111 | 112 | ![](images/12-1.png) 113 | 114 | 图12-1 Docker架构图 115 | 116 | 我们来讲解图中包含的组件。 117 | 118 | (1) Docker daemon(Docker守护进程) 119 | 120 | Docker daemon是一个运行在宿主机(DOCKER_HOST)的后台进程。我们可通过Docker客户端与之通信。 121 | 122 | (2) Client(Docker客户端) 123 | 124 | Docker客户端是Docker的用户界面,它可以接受用户命令和配置标识,并与Docker daemon通信。图中,docker build等都是Docker的相关命令。 125 | 126 | (3) Images(Docker镜像) 127 | 128 | Docker镜像是一个只读模板,它包含创建Docker容器的说明。它和系统安装光盘有点像——我们使用系统安装光盘安装系统,同理,我们使用Docker镜像运行Docker镜像中的程序。 129 | 130 | (4) Container(容器) 131 | 132 | 容器是镜像的可运行实例。镜像和容器的关系有点类似于面向对象中,类和对象的关系。我们可通过Docker API或者CLI命令来启停、移动、删除容器。 133 | 134 | (5) Registry 135 | 136 | Docker Registry是一个集中存储与分发镜像的服务。我们构建完Docker镜像后,就可在当前宿主机上运行。但如果想要在其他机器上运行这个镜像,我们就需要手动拷贝。此时,我们可借助Docker Registry来避免镜像的手动拷贝。 137 | 138 | 一个Docker Registry可包含多个Docker仓库;每个仓库可包含多个镜像标签;每个标签对应一个Docker镜像。这跟Maven的仓库有点类似,如果把Docker Registry比作Maven仓库的话,那么Docker仓库就可理解为某jar包的路径,而镜像标签则可理解为jar包的版本号。 139 | 140 | Docker Registry可分为公有Docker Registry和私有Docker Registry。最常用的Docker Registry莫过于官方的Docker Hub,这也是默认的Docker Registry。Docker Hub上存放着大量优秀的镜像,我们可使用Docker命令下载并使用。 141 | 142 | 143 | 144 | ## 1.6 Docker与虚拟机 145 | 146 | ![](images/docker-vs-vm.png) 147 | 148 | * Hypervisor层被Docker Engine取代。 149 | * Hypervisor: 150 | * 虚拟化粒度不同 151 | * 虚拟机利用Hypervisor虚拟化CPU、内存、IO设备等实现的,然后在其上运行完整的操作系统,再在该系统上运行所需的应用。资源隔离级别:OS级别 152 | * 运行在Docker容器中的应用直接运行于宿主机的内核,容器共享宿主机的内核,容器内部运行的是Linux副本,没有自己的内核,直接使用物理机的硬件资源,因此CPU/内存利用率上有一定优势。资源隔离级别:利用Linux内核本身支持的容器方式实现资源和环境隔离。 153 | * 拓展阅读 154 | * 《Docker、LXC、Cgroup的结构关系》: 155 | 156 | 157 | 158 | 159 | ## 1.7 Docker应用场景 160 | 161 | * 八个Docker的真实应用场景: -------------------------------------------------------------------------------- /docker/第1章-Docker入门/02-Docker安装.md: -------------------------------------------------------------------------------- 1 | # Docker安装 2 | 3 | ## 2.1 CentOS 4 | 5 | ### 2.1.1 系统要求 6 | 7 | * **CentOS 7**或更高版本 8 | * `centos-extras` 仓库必须处于启用状态,该仓库默认启用,但如果您禁用了该仓库,请按照 中的描述重新启用。 9 | * 建议使用`overlay2` 存储驱动 10 | 11 | ### 2.1.2 yum安装 12 | 13 | #### 2.1.2.1 卸载老版本的Docker 14 | 15 | 在CentOS中,老版本Docker名称是`docker` 或`docker-engine` ,而Docker CE的软件包名称是`docker-ce` 。因此,如已安装过老版本的Docker,需使用如下命令卸载。 16 | 17 | ```Shell 18 | sudo yum remove docker \ 19 | docker-common \ 20 | docker-selinux \ 21 | docker-engine 22 | ``` 23 | 24 | 需要注意的是,执行该命令只会卸载Docker本身,而不会删除Docker存储的文件,例如镜像、容器、卷以及网络文件等。这些文件保存在`/var/lib/docker` 目录中,需要手动删除。 25 | 26 | #### 2.1.2.2 安装仓库 27 | 28 | 1. 执行以下命令,安装Docker所需的包。其中,`yum-utils` 提供了`yum-config-manager` 工具;`device-mapper-persistent-data` 及 `lvm2` 则是`devicemapper` 存储驱动所需的包。 29 | 30 | ```Shell 31 | sudo yum install -y yum-utils device-mapper-persistent-data lvm2 32 | ``` 33 | 34 | 2. 执行如下命令,安装`stable` 仓库。必须安装`stable` 仓库,即使你想安装`edge` 或`test` 仓库中的Docker构建版本。 35 | 36 | ```Shell 37 | sudo yum-config-manager \ 38 | --add-repo \ 39 | https://download.docker.com/linux/centos/docker-ce.repo 40 | ``` 41 | 42 | 3. [**可选**] 执行如下命令,启用`edge` 及`test` 仓库。edge/test仓库其实也包含在了`docker.repo` 文件中,但默认是禁用的,可使用以下命令来启用。 43 | 44 | ```Shell 45 | sudo yum-config-manager --enable docker-ce-edge # 启用edge仓库 46 | sudo yum-config-manager --enable docker-ce-test # 启用test仓库 47 | ``` 48 | 49 | 如需再次禁用,可加上`--disable` 标签。例如,执行如下命令即可禁用edge仓库。 50 | 51 | ```shell 52 | sudo yum-config-manager --disable docker-ce-edge 53 | ``` 54 | 55 | **TIPS**:从Docker 17.06起,stable版本也会发布到edge以及test仓库中。 56 | 57 | 58 | #### 2.1.2.3 安装Docker CE 59 | 60 | 1. 执行以下命令,更新`yum`的包索引 61 | 62 | ```Shell 63 | sudo yum makecache fast 64 | ``` 65 | 66 | 2. 执行如下命令即可安装最新版本的Docker CE 67 | 68 | ```Shell 69 | sudo yum install docker-ce 70 | ``` 71 | 72 | 3. 在生产环境中,可能需要指定想要安装的版本,此时可使用如下命令列出当前可用的Docker版本。 73 | 74 | ```shell 75 | yum list docker-ce.x86_64 --showduplicates | sort -r 76 | ``` 77 | 78 | 这样,列出版本后,可使用如下命令,安装想要安装的Docker CE版本。 79 | 80 | ```shell 81 | sudo yum install docker-ce- 82 | ``` 83 | 84 | 4. 启动Docker 85 | 86 | ```Shell 87 | sudo systemctl start docker 88 | ``` 89 | 90 | 5. 验证安装是否正确。 91 | 92 | ```shell 93 | sudo docker run hello-world 94 | ``` 95 | 96 | 这样,Docker将会下载测试镜像,并使用该镜像启动一个容器。如能够看到类似如下的输出,则说明安装成功。 97 | 98 | ``` 99 | Unable to find image 'hello-world:latest' locally 100 | latest: Pulling from library/hello-world 101 | b04784fba78d: Pull complete 102 | Digest: sha256:f3b3b28a45160805bb16542c9531888519430e9e6d6ffc09d72261b0d26ff74f 103 | Status: Downloaded newer image for hello-world:latest 104 | 105 | Hello from Docker! 106 | This message shows that your installation appears to be working correctly. 107 | 108 | To generate this message, Docker took the following steps: 109 | 1. The Docker client contacted the Docker daemon. 110 | 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. 111 | 3. The Docker daemon created a new container from that image which runs the 112 | executable that produces the output you are currently reading. 113 | 4. The Docker daemon streamed that output to the Docker client, which sent it 114 | to your terminal. 115 | 116 | To try something more ambitious, you can run an Ubuntu container with: 117 | $ docker run -it ubuntu bash 118 | 119 | Share images, automate workflows, and more with a free Docker ID: 120 | https://cloud.docker.com/ 121 | 122 | For more examples and ideas, visit: 123 | https://docs.docker.com/engine/userguide/ 124 | ``` 125 | 126 | #### 2.1.2.4 升级Docker CE 127 | 128 | 如需升级Docker CE,只需执行如下命令: 129 | 130 | ```shell 131 | sudo yum makecache fast 132 | ``` 133 | 134 | 然后按照安装Docker的步骤,即可升级Docker。 135 | 136 | 137 | 138 | #### 2.1.2.5 参考文档 139 | 140 | CentOS 7安装Docker官方文档: ,文档中还讲解了在CentOS 7中安装Docker CE的其他方式,本文不作赘述。 141 | 142 | ### 2.1.3 shell一键安装 143 | 144 | ```shell 145 | curl -fsSL get.docker.com -o get-docker.sh 146 | sudo sh get-docker.sh 147 | ``` 148 | 149 | 搞定一切。 150 | 151 | ## 2.2 Ubuntu 152 | 153 | ### 2.2.1 系统要求 154 | 155 | * Docker支持以下版本的Ubuntu,要求64位。 156 | * Zesty 17.04 157 | * Xenial 16.04 (LTS) 158 | * Trusty 14.04 (LTS) 159 | * 支持运行的平台:`x86_64` 、`armhf` 、`s390x(IBM Z)` 。其中,如选择IBM Z,那么只支持Ubuntu Xenial以及Zesty。 160 | * 本文使用**Ubuntu 16.04 LTS**,下载地址: 161 | 162 | ### 2.2.2 安装步骤 163 | 164 | #### 2.2.2.1 卸载老版本Docker 165 | 166 | 在Ubuntu中,老版本的软件包名称是`docker` 或者`docker-engine` ,而Docker CE的软件包名称是`docker-ce` 。因此,如已安装过老版本的Docker,需要先卸载掉。执行以下命令,即可卸载老版本的Docker及其依赖。 167 | 168 | ```shell 169 | sudo apt-get remove docker docker-engine docker.io 170 | ``` 171 | 172 | 需要注意的是,执行该命令只会卸载Docker本身,而不会删除Docker内容,例如镜像、容器、卷以及网络。这些文件保存在`/var/lib/docker` 目录中,需要手动删除。 173 | 174 | #### 2.2.2.2 Ubuntu Trusty 14.04 额外建议安装的包 175 | 176 | 除非你有不得已的苦衷,否则强烈建议安装`linux-image-extra-*` 软件包,以便于Docker使用`aufs` 存储驱动。执行如下命令,即可安装`linux-image-extra-*` 。 177 | 178 | ```shell 179 | sudo apt-get update 180 | 181 | sudo apt-get install \ 182 | linux-image-extra-$(uname -r) \ 183 | linux-image-extra-virtual 184 | ``` 185 | 186 | 对于Ubuntu 16.04或更高版本,Linux内核包含了对OverlayFS的支持,Docker CE默认会使用`overlay2` 存储驱动。 187 | 188 | #### 2.2.2.3 安装仓库 189 | 190 | 1. 执行如下命令,更新`apt` 的包索引。 191 | 192 | ```shell 193 | sudo apt-get update 194 | ``` 195 | 196 | 2. 执行如下命令,从而允许`apt` 使用HTTPS仓库。 197 | 198 | ```shell 199 | sudo apt-get install \ 200 | apt-transport-https \ 201 | ca-certificates \ 202 | curl \ 203 | software-properties-common 204 | ``` 205 | 206 | 3. 添加Docker官方的GPG key 207 | 208 | ```shell 209 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 210 | ``` 211 | 212 | 确认指纹是`9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88` 。 213 | 214 | ```shell 215 | sudo apt-key fingerprint 0EBFCD88 216 | ``` 217 | 218 | 4. 执行如下命令,安装`stable` 仓库。无论如何都必须安装`stable` 仓库,即使你想安装`edge` 或`test` 仓库中的Docker构建。如需添加`edge` 或`test` 仓库,可在如下命令中的“stable" 后,添加`edge` 或`test` 或两者。请视自己Ubuntu所运行的平台来执行如下命令。 219 | **NOTE**:如下命令中的`lsb_release -cs` 子命令用于返回您Ubuntu的发行版名称,例如`xenial` 。有时,在例如Linux Mint这样的发行版中,您可能需要将如下命令中的`$(lsb_release -cs)` 更改为系统的父级Ubuntu发行版。例如,如果您使用的是Linux Mint Rafaela,则可以使用`trusty` 。 220 | **amd64**: 221 | 222 | ```shell 223 | $ sudo add-apt-repository \ 224 | "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 225 | $(lsb_release -cs) \ 226 | stable" 227 | ``` 228 | 229 | **armhf**: 230 | 231 | ```shell 232 | $ sudo add-apt-repository \ 233 | "deb [arch=armhf] https://download.docker.com/linux/ubuntu \ 234 | $(lsb_release -cs) \ 235 | stable" 236 | ``` 237 | 238 | **s390x**: 239 | 240 | ```Shell 241 | $ sudo add-apt-repository \ 242 | "deb [arch=s390x] https://download.docker.com/linux/ubuntu \ 243 | $(lsb_release -cs) \ 244 | stable" 245 | ``` 246 | **NOTE**:从Docker 17.06起,stable版本也会发布到edge以及test仓库中。 247 | 248 | 249 | #### 2.2.2.4 安装Docker CE 250 | 251 | 1. 执行如下命令,更新`apt` 包索引。 252 | 253 | ```shell 254 | sudo apt-get update 255 | ``` 256 | 257 | 2. 执行如下命令,即可安装最新版本的Docker CE。任何已存在的Docker将会被覆盖安装。 258 | 259 | ```shell 260 | sudo apt-get install docker-ce 261 | ``` 262 | **WARNING**:如启用了多个Docker仓库,使用命令apt-get install 或apt-get update 命令安装或升级时,如未指定版本,那么将会安装最新的版本。这可能不适合您的稳定性要求。 263 | 264 | 3. 在生产环境中,我们可能需要指定想要安装的版本,此时可使用如下命令列出当前可用的Docker版本。 265 | 266 | ```shell 267 | apt-cache madison docker-ce 268 | ``` 269 | 这样,列出版本后,可使用如下命令,安装想要安装的Docker CE版本。 270 | ```shell 271 | sudo apt-get install docker-ce= 272 | ``` 273 | Docker daemon会自动启动。 274 | 275 | 4. 验证安装是否正确。 276 | 277 | ```shell 278 | sudo docker run hello-world 279 | ``` 280 | 281 | 282 | #### 2.2.2.5 升级Docker CE 283 | 284 | 如需升级Docker CE,只需执行如下命令: 285 | 286 | ```shell 287 | sudo apt-get update 288 | ``` 289 | 290 | 然后按照安装Docker的步骤,即可升级Docker。 291 | 292 | #### 2.2.2.6 参考文档 293 | 294 | Ubuntu安装Docker官方文档: ,文档还讲解了在Ubuntu中安装Docker CE的其他方式,本文不作赘述。 295 | 296 | 297 | 298 | ## 2.3 macOS 299 | 300 | ### 2.3.1 系统要求 301 | 302 | macOS Yosemite 10.10.3或更高版本 303 | 304 | ### 2.3.2 安装步骤 305 | 306 | * 前往 ,点击页面右侧的“Get Docker”按钮,下载安装包; 307 | * 双击即可安装。 308 | 309 | 310 | 311 | 312 | ## 2.4 Windows(docker for windows) 313 | 314 | ### 2.4.1 系统要求 315 | 316 | Windows 10 Professional 或 Windows 10 Enterprise X64 317 | 318 | 对于Win 7,可使用Docker Toolbox(不建议使用) 319 | 320 | ### 2.4.2 安装步骤 321 | 322 | * 前往 ,点击页面右侧的“Get Docker”按钮,下载安装包; 323 | * 双击即可安装。 324 | 325 | 326 | 327 | 328 | 329 | ## 2.5 其他系统 330 | 331 | 详见官方文档: 332 | 333 | 334 | 335 | ## 2.6 加速安装 336 | 337 | 注册阿里云,参考该页面的内容安装即可: -------------------------------------------------------------------------------- /docker/第1章-Docker入门/03-配置镜像加速器.md: -------------------------------------------------------------------------------- 1 | # 配置镜像加速器 2 | 3 | 国内访问Docker Hub的速度很不稳定,有时甚至出现连接不上的情况。本节我们来为Docker配置镜像加速器,从而解决这个问题。目前国内很多云服务商都提供了镜像加速的服务。 4 | 5 | 常用的镜像加速器有:阿里云加速器、DaoCloud加速器等。各厂商镜像加速器的使用方式大致类似,笔者以阿里云加速器为例进行讲解。 6 | 7 | 1. 注册阿里云账号后,即可在阿里云控制台([https://cr.console.aliyun.com/#/accelerator](https://cr.console.aliyun.com/#/accelerator))看到类似如下的页面。 8 | 9 | ![](images/镜像加速器.png) 10 | 11 | 2. 按照图中的说明,即可配置镜像加速器。 -------------------------------------------------------------------------------- /docker/第1章-Docker入门/04-镜像常用命令.md: -------------------------------------------------------------------------------- 1 | # Docker镜像常用命令 2 | 3 | 我们首先来讨论Docker镜像的常用命令。 4 | 5 | ## 搜索镜像 6 | 7 | 可使用`docker search` 命令搜索存放在Docker Hub中的镜像。 8 | 9 | 命令格式: 10 | 11 | ``` 12 | docker search [OPTIONS] TERM 13 | ``` 14 | 15 | 参数: 16 | 17 | | Name, shorthand | Default | Description | 18 | | --------------- | ------- | ---------------- | 19 | | `--automated` | `false` | 只列出自动构建的镜像 | 20 | | `--filter, -f` | | 根据指定条件过滤结果 | 21 | | `--limit` | `25` | 搜索结果的最大条数 | 22 | | `--no-trunc` | `false` | 不截断输出,显示完整的输出 | 23 | | `--stars, -s` | `0` | 只展示Star不低于该数值的结果 | 24 | 25 | 示例1: 26 | 27 | ```shell 28 | docker search java 29 | ``` 30 | 31 | 执行该命令后,Docker就会在Docker Hub中搜索含有“java”这个关键词的镜像仓库。执行该命令后,可看到类似于如下的表格: 32 | 33 | ``` 34 | NAME DESCRIPTION STARS OFFICIAL AUTOMATED 35 | java Java is a concurrent, ... 1281 [OK] 36 | anapsix/alpine-java Oracle Java 8 (and 7) ... 190 [OK] 37 | isuper/java-oracle This repository conta ... 48 [OK] 38 | lwieske/java-8 Oracle Java 8 Contain ... 32 [OK] 39 | nimmis/java-centos This is docker images ... 23 [OK] 40 | ... 41 | ``` 42 | 43 | 该表格包含五列,含义如下: 44 | 45 | ① NAME:镜像仓库名称。 46 | 47 | ② DESCRIPTION:镜像仓库描述。 48 | 49 | ③ STARS:镜像仓库收藏数,表示该镜像仓库的受欢迎程度,类似于GitHub的Stars。 50 | 51 | ④ OFFICAL:表示是否为官方仓库,该列标记为[OK]的镜像均由各软件的官方项目组创建和维护。由结果可知,java这个镜像仓库是官方仓库,而其他的仓库都不是镜像仓库。 52 | 53 | ⑤ AUTOMATED:表示是否是自动构建的镜像仓库。 54 | 55 | 示例2: 56 | 57 | ``` 58 | docker search -s 10 java 59 | ``` 60 | 61 | 62 | 63 | ## 下载镜像[重要] 64 | 65 | 使用命令`docker pull` 命令即可从Docker Registry上下载镜像。 66 | 67 | 命令格式: 68 | 69 | ``` 70 | docker pull [OPTIONS] NAME[:TAG|@DIGEST] 71 | ``` 72 | 73 | 参数: 74 | 75 | | Name, shorthand | Default | Description | 76 | | ------------------------- | ------- | ----------- | 77 | | `--all-tags, -a` | `false` | 下载所有标签的镜像 | 78 | | `--disable-content-trust` | `true` | 忽略镜像的校验 | 79 | 80 | 示例1: 81 | 82 | ```shell 83 | docker pull java 84 | ``` 85 | 86 | 执行该命令后,Docker会从Docker Hub中的java仓库下载最新版本的Java镜像。 87 | 88 | 示例2: 89 | 90 | 该命令还可指定想要下载的镜像标签以及Docker Registry地址,例如: 91 | 92 | ```shell 93 | docker pull reg.itmuch.com/java:7 94 | ``` 95 | 96 | 这样就可以从指定的Docker Registry中下载标签为7的Java镜像。 97 | 98 | 99 | 100 | ## 列出镜像[重要] 101 | 102 | 使用`docker images` 命令即可列出已下载的镜像。 103 | 104 | 执行该命令后,将会看到类似于如下的表格: 105 | 106 | ``` 107 | REPOSITORY TAG IMAGE ID CREATED SIZE 108 | java latest 861e95c114d6 4 weeks ago 643.1 MB 109 | hello-world latest c54a2cc56cbb 5 months ago 1.848 kB 110 | ``` 111 | 112 | 该表格包含了5列,含义如下: 113 | 114 | ① REPOSITORY:镜像所属仓库名称。 115 | 116 | ② TAG:镜像标签。默认是latest,表示最新。 117 | 118 | ③ IMAGE ID:镜像ID,表示镜像唯一标识。 119 | 120 | ④ CREATED:镜像创建时间。 121 | 122 | ⑤ SIZE:镜像大小。 123 | 124 | 命令格式: 125 | 126 | ``` 127 | docker images [OPTIONS] [REPOSITORY[:TAG]] 128 | ``` 129 | 130 | 参数: 131 | 132 | | Name, shorthand | Default | Description | 133 | | --------------- | ------- | -------------------------------- | 134 | | `--all, -a` | `false` | 列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层) | 135 | | `--digests` | `false` | 显示摘要信息 | 136 | | `--filter, -f` | | 显示满足条件的镜像 | 137 | | `--format` | | 通过Go语言模板文件展示镜像 | 138 | | `--no-trunc` | `false` | 不截断输出,显示完整的镜像信息 | 139 | | `--quiet, -q` | `false` | 只显示镜像ID | 140 | 141 | 示例: 142 | 143 | ``` 144 | docker images 145 | docker images java 146 | docker images java:8 147 | docker images --digests 148 | docker images --filter "dangling=true" # 展示虚悬镜像 149 | ``` 150 | 151 | 152 | 153 | ## 删除本地镜像[重要] 154 | 155 | 使用`docker rmi` 命令即可删除指定镜像。 156 | 157 | 命令格式: 158 | 159 | ``` 160 | docker rmi [OPTIONS] IMAGE [IMAGE...] 161 | ``` 162 | 163 | 参数: 164 | 165 | | Name, shorthand | Default | Description | 166 | | --------------- | ------- | ---------------- | 167 | | `--force, -f` | `false` | 强制删除 | 168 | | `--no-prune` | `false` | 不移除该镜像的过程镜像,默认移除 | 169 | 170 | 例1:删除指定名称的镜像。 171 | 172 | ```shell 173 | docker rmi hello-world 174 | ``` 175 | 176 | 表示删除hello-world这个镜像。 177 | 178 | 例2:删除所有镜像。 179 | 180 | ``` 181 | docker rmi -f $(docker images) 182 | ``` 183 | 184 | -f参数表示强制删除。 185 | 186 | 187 | 188 | ## 保存镜像 189 | 190 | 使用`docker save` 即可保存镜像。 191 | 192 | 命令格式: 193 | 194 | ``` 195 | docker save [OPTIONS] IMAGE [IMAGE...] 196 | ``` 197 | 198 | 参数: 199 | 200 | | Name, shorthand | Default | Description | 201 | | --------------- | ------- | ---------------------------------- | 202 | | `--output, -o` | | Write to a file, instead of STDOUT | 203 | 204 | 例1: 205 | 206 | ```shell 207 | docker save busybox > busybox.tar 208 | docker save --output busybox.tar busybox 209 | ``` 210 | 211 | 212 | 213 | ## 加载镜像 214 | 215 | 使用`docker load` 命令即可加载镜像。 216 | 217 | 命令格式: 218 | 219 | ```shell 220 | docker load [OPTIONS] 221 | ``` 222 | 223 | 参数: 224 | 225 | | Name, shorthand | Default | Description | 226 | | --------------- | ------- | ------------ | 227 | | `--input, -i` | | 从文件加载而非STDIN | 228 | | `--quiet, -q` | `false` | 静默加载 | 229 | 230 | 例1: 231 | 232 | ```shell 233 | docker load < busybox.tar.gz 234 | docker load --input fedora.tar 235 | ``` 236 | 237 | 238 | 239 | ## 构建镜像[重要] 240 | 241 | 通过Dockerfile构建镜像。 242 | 243 | 命令格式: 244 | 245 | ``` 246 | docker build [OPTIONS] PATH | URL | - 247 | ``` 248 | 249 | 参数: 250 | 251 | | Name, shorthand | Default | Description | 252 | | ------------------------- | --------- | ---------------------------------------- | 253 | | `--add-host` | | 添加自定义从host到IP的映射,格式为(host:ip) | 254 | | `--build-arg` | | 设置构建时的变量 | 255 | | `--cache-from` | | 作为缓存源的镜像 | 256 | | `--cgroup-parent` | | 容器可选的父cgroup | 257 | | `--compress` | `false` | 使用gzip压缩构建上下文 | 258 | | `--cpu-period` | `0` | 限制CPU CFS (Completely Fair Scheduler) 周期 | 259 | | `--cpu-quota` | `0` | 限制CPU CFS (Completely Fair Scheduler) 配额 | 260 | | `--cpu-shares, -c` | `0` | CPU使用权重(相对权重) | 261 | | `--cpuset-cpus` | | 指定允许执行的CPU | 262 | | `--cpuset-mems` | | 指定允许执行的内存 | 263 | | `--disable-content-trust` | `true` | 忽略校验 | 264 | | `--file, -f` | | 指定Dockerfile的名称,默认是‘PATH/Dockerfile’ | 265 | | `--force-rm` | `false` | 删除中间容器 | 266 | | `--iidfile` | | 将镜像ID写到文件中 | 267 | | `--isolation` | | 容器隔离技术 | 268 | | `--label` | | 设置镜像使用的元数据 | 269 | | `--memory, -m` | `0` | 设置内存限制 | 270 | | `--memory-swap` | `0` | 设置Swap的最大值为内存+swap,如果设置为-1表示不限swap | 271 | | `--network` | `default` | 在构建期间设置RUN指令的网络模式 | 272 | | `--no-cache` | `false` | 构建镜像过程中不使用缓存 | 273 | | `--pull` | `false` | 总是尝试去更新镜像的新版本 | 274 | | `--quiet, -q` | `false` | 静默模式,构建成功后只输出镜像ID | 275 | | `--rm` | `true` | 构建成功后立即删除中间容器 | 276 | | `--security-opt` | | 安全选项 | 277 | | `--shm-size` | `0` | 指定`/dev/shm` 目录的大小 | 278 | | `--squash` | `false` | 将构建的层压缩成一个新的层 | 279 | | `--tag, -t` | | 设置标签,格式:name:tag,tag可选 | 280 | | `--target` | | 设置构建时的目标构建阶段 | 281 | | `--ulimit` | | Ulimit 选项 | 282 | 283 | 284 | 285 | **拓展阅读** 286 | 287 | Docker命令: -------------------------------------------------------------------------------- /docker/第1章-Docker入门/05-容器常用命令.md: -------------------------------------------------------------------------------- 1 | # 容器常用命令 2 | 3 | 本节我们来讨论Docker容器的常用命令。 4 | 5 | 6 | 7 | ## 新建并启动容器[重要] 8 | 9 | 使用以下`docker run` 命令即可新建并启动一个容器。该命令是我们最常用的命令了,它有很多选项,下面笔者列举一些常用的选项。 10 | 11 | ① -d选项:表示后台运行 12 | 13 | ② -P选项:随机端口映射 14 | 15 | ③ -p选项:指定端口映射,有以下四种格式。 16 | 17 | ip:hostPort:containerPort 18 | 19 | ip::containerPort 20 | 21 | hostPort:containerPort 22 | 23 | containerPort 24 | 25 | ④ --network选项:指定网络模式,该选项有以下可选参数: 26 | 27 | --network=bridge: 默认选项,表示连接到默认的网桥。 28 | 29 | --network=host:容器使用宿主机的网络。 30 | 31 | --network=container:NAME_or_ID:告诉Docker让新建的容器使用已有容器的网络配置。 32 | 33 | --network=none:不配置该容器的网络,用户可自定义网络配置。 34 | 35 | 示例1: 36 | 37 | ```shell 38 | docker run java /bin/echo 'Hello World' 39 | ``` 40 | 41 | 这样终端会打印Hello World的字样,跟在本地直接执行`/bin/echo 'Hello World'` 一样。 42 | 43 | 示例2: 44 | 45 | ```shell 46 | docker run -d -p 91:80 nginx 47 | ``` 48 | 49 | 这样就能启动一个Nginx容器。在本例中,我们为docker run添加了两个参数,含义如下: 50 | 51 | ```shell 52 | -d # 后台运行 53 | -p 宿主机端口:容器端口 # 开放容器端口到宿主机端口 54 | ``` 55 | 56 | 访问[http://Docker宿主机IP:91/](http://Docker宿主机IP:91/) ,将会看到如图12-3的界面: 57 | 58 | ![](images/12-3.png) 59 | 60 | 图12-3 Nginx首页 61 | 62 | **TIPS** 63 | 64 | 需要注意的是,使用docker run命令创建容器时,会先检查本地是否存在指定镜像。如果本地不存在该名称的镜像,Docker就会自动从Docker Hub下载镜像并启动一个Docker容器。 65 | 66 | 67 | 68 | ## 列出容器[重要] 69 | 70 | 使用`docker ps` 命令即可列出运行中的容器。执行该命令后,可看到类似于如下的表格。 71 | 72 | ``` 73 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 74 | 784fd3b294d7 nginx "nginx -g 'daemon off" 20 minutes ago Up 2 seconds 443/tcp, 0.0.0.0:91->80/tcp backstabbing_archimedes 75 | ``` 76 | 77 | 如需列出所有容器(包括已停止的容器),可使用-a参数。 78 | 79 | 该表格包含了七列,含义如下: 80 | 81 | ① CONTAINER_ID:表示容器ID。 82 | 83 | ② IMAGE:表示镜像名称。 84 | 85 | ③ COMMAND:表示启动容器时运行的命令。 86 | 87 | ④ CREATED:表示容器的创建时间。 88 | 89 | ⑤ STATUS:表示容器运行的状态。Up表示运行中,Exited表示已停止。 90 | 91 | ⑥ PORTS:表示容器对外的端口号。 92 | 93 | ⑦ NAMES:表示容器名称。该名称默认由Docker自动生成,也可使用docker run命令的--name选项自行指定。 94 | 95 | 命令格式: 96 | 97 | ``` 98 | docker ps [OPTIONS] 99 | ``` 100 | 101 | 参数: 102 | 103 | | Name, shorthand | Default | Description | 104 | | --------------- | ------- | -------------------------- | 105 | | `--all, -a` | `false` | 列出所有容器,包括未运行的容器,默认只展示运行的容器 | 106 | | `--filter, -f` | | 根据条件过滤显示内容 | 107 | | `--format` | | 通过Go语言模板文件展示镜像 | 108 | | `--last, -n` | `-1` | 显示最近创建n个容器(包含所有状态) | 109 | | `--latest, -l` | `false` | 显示最近创建的容器(包含所有状态) | 110 | | `--no-trunc` | `false` | 不截断输出 | 111 | | `--quiet, -q` | `false` | 静默模式,只展示容器的编号 | 112 | | `--size, -s` | `false` | 显示总文件大小 | 113 | 114 | 示例: 115 | 116 | ``` 117 | docker ps -n 5 118 | docker ps -a -q 119 | ``` 120 | 121 | 122 | 123 | ## 停止容器[重要] 124 | 125 | 使用`docker stop` 命令,即可停止容器。 126 | 127 | 命令格式: 128 | 129 | ``` 130 | docker stop [OPTIONS] CONTAINER [CONTAINER...] 131 | ``` 132 | 133 | 参数: 134 | 135 | | Name, shorthand | Default | Description | 136 | | --------------- | ------- | ----------------- | 137 | | `--time, -t` | `10` | 强制杀死容器前等待的时间,单位是秒 | 138 | 139 | 示例: 140 | 141 | ```shell 142 | docker stop 784fd3b294d7 143 | ``` 144 | 145 | 其中`784fd3b294d7` 是容器ID,当然也可使用`docker stop 容器名称` 来停止指定容器。 146 | 147 | 148 | 149 | ## 强制停止容器[重要] 150 | 151 | 可使用`docker kill` 命令停止一个或更多运行着的容器。 152 | 153 | 命令格式: 154 | 155 | ``` 156 | docker kill [OPTIONS] CONTAINER [CONTAINER...] 157 | ``` 158 | 159 | 参数: 160 | 161 | | Name, shorthand | Default | Description | 162 | | --------------- | ------- | ----------- | 163 | | `--signal, -s` | `KILL` | 向容器发送一个信号 | 164 | 165 | 例如: 166 | 167 | ```shell 168 | docker kill 784fd3b294d7 169 | ``` 170 | 171 | 172 | 173 | ## 启动已停止的容器[重要] 174 | 175 | 使用`docker run` 命令,即可新建并启动一个容器。对于已停止的容器,可使用`docker start` 命令来启动。 176 | 177 | 命令格式: 178 | 179 | ``` 180 | docker start [OPTIONS] CONTAINER [CONTAINER...] 181 | ``` 182 | 183 | 参数: 184 | 185 | | Name, shorthand | Default | Description | 186 | | ------------------- | ------- | -------------------- | 187 | | `--attach, -a` | `false` | 连接STDOUT/STDERR并转发信号 | 188 | | `--checkpoint` | | 从该检查点还原 | 189 | | `--checkpoint-dir` | | 使用自定义的检查点存储目录 | 190 | | `--detach-keys` | | 覆盖断开容器的关键顺序 | 191 | | `--interactive, -i` | `false` | 连接容器的STDIN | 192 | 193 | 例如: 194 | 195 | ```shell 196 | docker start 784fd3b294d7 197 | ``` 198 | 199 | 200 | 201 | ## 重启容器[重要] 202 | 203 | 可使用`docker restart` 命令来重启容器。该命令实际上是先执行了`docker stop` 命令,然后执行了`docker start` 命令。 204 | 205 | 命令格式: 206 | 207 | ``` 208 | docker restart [OPTIONS] CONTAINER [CONTAINER...] 209 | ``` 210 | 211 | 参数: 212 | 213 | | Name, shorthand | Default | Description | 214 | | --------------- | ------- | --------------- | 215 | | `--time, -t` | `10` | 关闭容器前等待的时间,单位是秒 | 216 | 217 | 218 | 219 | ## 进入容器[重要] 220 | 221 | 某场景下,我们可能需要进入运行中的容器。 222 | 223 | ① 使用`docker attach` 命令进入容器。 224 | 225 | 例如: 226 | 227 | ```shell 228 | docker attach 784fd3b294d7 229 | ``` 230 | 231 | 很多场景下,使用`docker attach` 命令并不方便。当多个窗口同时attach到同一个容器时,所有窗口都会同步显示。同理,如果某个窗口发生阻塞,其他窗口也无法执行操作。 232 | 233 | ② 使用`nsenter` 进入容器 234 | 235 | nsenter工具包含在util-linux 2.23或更高版本中。为了连接到容器,我们需要找到容器第一个进程的PID,可通过以下命令获取: 236 | 237 | ```shell 238 | docker inspect --format "{{.State.Pid}}" $CONTAINER_ID 239 | ``` 240 | 241 | 获得PID后,就可使用nsenter命令进入容器了: 242 | 243 | ```shell 244 | nsenter --target "$PID" --mount --uts --ipc --net --pid 245 | ``` 246 | 247 | 下面给出一个完整的例子: 248 | 249 | ``` 250 | [root@localhost ~]# docker ps 251 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 252 | 784fd3b294d7 nginx "nginx -g 'daemon off" 55 minutes ago Up 3 minutes 443/tcp, 0.0.0.0:91->80/tcp backstabbing_archimedes 253 | [root@localhost ~]# docker inspect --format "{{.State.Pid}}" 784fd3b294d7 254 | 95492 255 | [root@localhost ~]# nsenter --target 95492 --mount --uts --ipc --net --pid 256 | root@784fd3b294d7:/# 257 | ``` 258 | 259 | 读者也可将以上两条命令封装成一个Shell,从而简化进入容器的过程。 260 | 261 | ③ docker exec 262 | 263 | ```shell 264 | docker exec -it 容器id /bin/bash 265 | ``` 266 | 267 | 268 | 269 | ## 删除容器[重要] 270 | 271 | 使用`docker rm` 命令即可删除指定容器。 272 | 273 | 命令格式 274 | 275 | ``` 276 | docker rm [OPTIONS] CONTAINER [CONTAINER...] 277 | ``` 278 | 279 | 参数: 280 | 281 | | Name, shorthand | Default | Description | 282 | | --------------- | ------- | ----------------------- | 283 | | `--force, -f` | `false` | 通过SIGKILL信号强制删除正在运行中的容器 | 284 | | `--link, -l` | `false` | 删除容器间的网络连接 | 285 | | `--volumes, -v` | `false` | 删除与容器关联的卷 | 286 | 287 | 例1:删除指定容器。 288 | 289 | ```shell 290 | docker rm 784fd3b294d7 291 | ``` 292 | 293 | 该命令只能删除已停止的容器,如需删除正在运行的容器,可使用-f参数。 294 | 295 | 例2:删除所有的容器。 296 | 297 | ```shell 298 | docker rm -f $(docker ps -a -q) 299 | ``` 300 | 301 | 302 | 303 | ## 导出容器 304 | 305 | 将容器导出成一个压缩包文件。 306 | 307 | 命令格式: 308 | 309 | ``` 310 | docker export [OPTIONS] CONTAINER 311 | ``` 312 | 313 | 参数: 314 | 315 | | Name, shorthand | Default | Description | 316 | | --------------- | ------- | --------------- | 317 | | `--output, -o` | | 将内容写到文件而非STDOUT | 318 | 319 | 示例: 320 | 321 | ``` 322 | docker export red_panda > latest.tar 323 | docker export --output="latest.tar" red_panda 324 | ``` 325 | 326 | 327 | 328 | ## 导入容器 329 | 330 | 使用`docker import` 命令即可从归档文件导入内容并创建镜像。 331 | 332 | 命令格式: 333 | 334 | ``` 335 | docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]] 336 | ``` 337 | 338 | 参数: 339 | 340 | | Name, shorthand | Default | Description | 341 | | --------------- | ------- | --------------------- | 342 | | `--change, -c` | | 将Dockerfile指令应用到创建的镜像 | 343 | | `--message, -m` | | 为导入的镜像设置提交信息 | 344 | 345 | 示例: 346 | 347 | ``` 348 | docker import nginx2.tar nginx 349 | ``` 350 | 351 | 352 | 353 | 354 | 355 | **拓展阅读** 356 | 357 | * Docker的网络: 358 | * Docker命令: -------------------------------------------------------------------------------- /docker/第1章-Docker入门/06-实战:修改Nginx首页.md: -------------------------------------------------------------------------------- 1 | # 实战:修改Nginx首页 2 | 3 | ## 6.1 需求 4 | 5 | * 启动一个Nginx容器。 6 | * 将Nginx容器的首页改为`Welcome to 51CTO docker class` 。 7 | * 将容器保存下来。 8 | 9 | 10 | 11 | 12 | 13 | ## 6.2 提示 14 | 15 | * Nginx默认首页目录在:`/usr/share/nginx/html/index.html` 16 | 17 | 18 | 19 | 20 | ## 答案 21 | 22 | ``` 23 | docker exec -it nginx容器ID /bin/bash # 进入容器 24 | ``` 25 | 26 | 执行如下命令,修改/usr/share/nginx/html/index.html 27 | 28 | ``` 29 | tee index.html <<-'EOF' 30 | Welcome to 51CTO docker class 31 | EOF 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /docker/第1章-Docker入门/07-复习.md: -------------------------------------------------------------------------------- 1 | # 复习 2 | 3 | * Docker简介 4 | * 安装Docker 5 | * 镜像加速器 6 | * Docker常用命令 7 | 8 | #### -------------------------------------------------------------------------------- /docker/第1章-Docker入门/images/12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第1章-Docker入门/images/12-1.png -------------------------------------------------------------------------------- /docker/第1章-Docker入门/images/12-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第1章-Docker入门/images/12-3.png -------------------------------------------------------------------------------- /docker/第1章-Docker入门/images/13-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第1章-Docker入门/images/13-2.png -------------------------------------------------------------------------------- /docker/第1章-Docker入门/images/13-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第1章-Docker入门/images/13-3.png -------------------------------------------------------------------------------- /docker/第1章-Docker入门/images/docker-registry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第1章-Docker入门/images/docker-registry.jpg -------------------------------------------------------------------------------- /docker/第1章-Docker入门/images/docker-vs-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第1章-Docker入门/images/docker-vs-vm.png -------------------------------------------------------------------------------- /docker/第1章-Docker入门/images/nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第1章-Docker入门/images/nexus.png -------------------------------------------------------------------------------- /docker/第1章-Docker入门/images/镜像加速器.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第1章-Docker入门/images/镜像加速器.png -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/08-1-Dockerfile最佳实践.md: -------------------------------------------------------------------------------- 1 | Dockerfile最佳实践 2 | 3 | * 原文: 4 | * 译文: -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/08-Dockerfile指令详解.md: -------------------------------------------------------------------------------- 1 | # Dockerfile指令详解 2 | 3 | 在前面的例子中,我们提到了FROM、RUN指令。事实上,Dockerfile有十多个指令。本节我们来系统讲解这些指令,指令的一般格式为`指令名称 参数` 。 4 | 5 | 6 | 7 | 8 | 9 | ## ADD 复制文件 10 | 11 | ADD指令用于复制文件,格式为: 12 | 13 | - `ADD ... ` 14 | - `ADD ["",... ""]` 15 | 16 | 从src目录复制文件到容器的dest。其中src可以是Dockerfile所在目录的相对路径,也可以是一个URL,还可以是一个压缩包 17 | 18 | **注意**: 19 | 20 | ① src必须在构建的上下文内,不能使用例如:`ADD ../somethine /something` 这样的命令,因为`docker build` 命令首先会将上下文路径和其子目录发送到docker daemon。 21 | 22 | ② 如果src是一个URL,同时dest不以斜杠结尾,dest将会被视为文件,src对应内容文件将会被下载到dest。 23 | 24 | ③ 如果src是一个URL,同时dest以斜杠结尾,dest将被视为目录,src对应内容将会被下载到dest目录。 25 | 26 | ④ 如果src是一个目录,那么整个目录下的内容将会被拷贝,包括文件系统元数据。 27 | 28 | ⑤ 如果文件是可识别的压缩包格式,则docker会自动解压。 29 | 30 | 示例: 31 | 32 | ```dockerfile 33 | ADD microservice-discovery-eureka-0.0.1-SNAPSHOT.jar app.jar 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | ## ARG 设置构建参数 41 | 42 | ARG指令用于设置构建参数,类似于ENV。和ARG不同的是,ARG设置的是构建时的环境变量,在容器运行时是不会存在这些变量的。 43 | 44 | 格式为: 45 | 46 | - `ARG [=]` 47 | 48 | 示例: 49 | 50 | ```dockerfile 51 | ARG user1=someuser 52 | ``` 53 | 54 | 详细介绍文档: 55 | 56 | 57 | 58 | ## CMD 容器启动命令 59 | 60 | CMD指令用于为执行容器提供默认值。每个Dockerfile只有一个CMD命令,如果指定了多个CMD命令,那么只有最后一条会被执行,如果启动容器的时候指定了运行的命令,则会覆盖掉CMD指定的命令。 61 | 62 | 支持三种格式: 63 | 64 | `CMD ["executable","param1","param2"]` (推荐使用) 65 | 66 | `CMD ["param1","param2"]` (为ENTRYPOINT指令提供预设参数) 67 | 68 | `CMD command param1 param2` (在shell中执行) 69 | 70 | 示例: 71 | 72 | ```dockerfile 73 | CMD echo "This is a test." | wc - 74 | ``` 75 | 76 | 77 | 78 | 79 | 80 | ## COPY 复制文件 81 | 82 | 复制文件,格式为: 83 | 84 | - `COPY ... ` 85 | - `COPY ["",... ""]` 86 | 87 | 复制本地端的src到容器的dest。COPY指令和ADD指令类似,COPY不支持URL和压缩包。 88 | 89 | 90 | 91 | 92 | 93 | ## ENTRYPOINT 入口点 94 | 95 | 格式为: 96 | 97 | - `ENTRYPOINT ["executable", "param1", "param2"]` 98 | - `ENTRYPOINT command param1 param2` 99 | 100 | ENTRYPOINT和CMD指令的目的一样,都是指定Docker容器启动时执行的命令,可多次设置,但只有最后一个有效。ENTRYPOINT不可被重写覆盖。 101 | 102 | ENTRYPOINT、CMD区别: 103 | 104 | 105 | 106 | 107 | 108 | ## ENV 设置环境变量 109 | 110 | ENV指令用于设置环境变量,格式为: 111 | 112 | - `ENV ` 113 | - `ENV = ...` 114 | 115 | 示例: 116 | 117 | ```dockerfile 118 | ENV JAVA_HOME /path/to/java 119 | ``` 120 | 121 | 122 | 123 | 124 | 125 | ## EXPOSE 声明暴露的端口 126 | 127 | EXPOSE指令用于声明在运行时容器提供服务的端口,格式为: 128 | 129 | - `EXPOSE [...]` 130 | 131 | 需要注意的是,这只是一个声明,运行时并不会因为该声明就打开相应端口。该指令的作用主要是帮助镜像使用者理解该镜像服务的守护端口;其次是当运行时使用随机映射时,会自动映射EXPOSE的端口。示例: 132 | 133 | ```dockerfile 134 | # 声明暴露一个端口示例 135 | EXPOSE port1 136 | # 相应的运行容器使用的命令 137 | docker run -p port1 image 138 | # 也可使用-P选项启动 139 | docker run -P image 140 | 141 | # 声明暴露多个端口示例 142 | EXPOSE port1 port2 port3 143 | # 相应的运行容器使用的命令 144 | docker run -p port1 -p port2 -p port3 image 145 | # 也可指定需要映射到宿主机器上的端口号 146 | docker run -p host_port1:port1 -p host_port2:port2 -p host_port3:port3 image 147 | ``` 148 | 149 | 150 | 151 | 152 | 153 | ## FROM 指定基础镜像 154 | 155 | 使用FROM指令指定基础镜像,FROM指令有点像Java里面的“extends”关键字。需要注意的是,FROM指令必须指定且需要写在其他指令之前。FROM指令后的所有指令都依赖于该指令所指定的镜像。 156 | 157 | 支持三种格式: 158 | 159 | - `FROM ` 160 | - `FROM :` 161 | - `FROM @` 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | ## LABEL 为镜像添加元数据 170 | 171 | LABEL指令用于为镜像添加元数据。 172 | 173 | 格式为: 174 | 175 | - `LABEL = = = ...` 176 | 177 | 使用 ”"“和”\\“转换命令行,示例: 178 | 179 | ```dockerfile 180 | LABEL "com.example.vendor"="ACME Incorporated" 181 | LABEL com.example.label-with-value="foo" 182 | LABEL version="1.0" 183 | LABEL description="This text illustrates \ 184 | that label-values can span multiple lines." 185 | ``` 186 | 187 | 188 | 189 | 190 | 191 | ## MAINTAINER 指定维护者的信息(已过时) 192 | 193 | MAINTAINER指令用于指定维护者的信息,用于为Dockerfile署名。 194 | 195 | 格式为: 196 | 197 | - `MAINTAINER ` 198 | 199 | 示例: 200 | 201 | ``` 202 | MAINTAINER 周立 203 | ``` 204 | 205 | 注:该指令已过时,建议使用如下形式: 206 | 207 | ``` 208 | LABEL maintainer="SvenDowideit@home.org.au" 209 | ``` 210 | 211 | 212 | 213 | ## RUN 执行命令 214 | 215 | 该指令支持两种格式: 216 | 217 | - `RUN `  218 | - `RUN ["executable", "param1", "param2"]` 219 | 220 | `RUN ` 在shell终端中运行,在Linux中默认是`/bin/sh -c` ,在Windows中是 `cmd /s /c` ,使用这种格式,就像直接在命令行中输入命令一样。 221 | `RUN ["executable", "param1", "param2"]` 使用exec执行,这种方式类似于函数调用。指定其他终端可以通过该方式操作,例如:`RUN ["/bin/bash", "-c", "echo hello"]` ,该方式必须使用双引号["]而不能使用单引号['],因为该方式会被转换成一个JSON 数组。 222 | 223 | 224 | 225 | 226 | 227 | ## USER 设置用户 228 | 229 | 该指令用于设置启动镜像时的用户或者UID,写在该指令后的RUN、CMD以及ENTRYPOINT指令都将使用该用户执行命令。 230 | 231 | 格式为: 232 | 233 | - `USER 用户名` 234 | 235 | 示例: 236 | 237 | ```dockerfile 238 | USER daemon 239 | ``` 240 | 241 | 242 | 243 | 244 | 245 | ## VOLUME 指定挂载点 246 | 247 | 该指令使容器中的一个目录具有持久化存储的功能,该目录可被容器本身使用,也可共享给其他容器。当容器中的应用有持久化数据的需求时可以在Dockerfile中使用该指令。格式为: 248 | 249 | - `VOLUME ["/data"]` 250 | 251 | 示例: 252 | 253 | ```dockerfile 254 | VOLUME /data 255 | ``` 256 | 257 | 使用示例: 258 | 259 | ```dockerfile 260 | FROM nginx 261 | VOLUME /tmp 262 | ``` 263 | 264 | 当该Dockerfile被构建成镜像后,/tmp目录中的数据即使容器关闭也依然存在。如果另一个容器也有持久化的需求,并且想使用以上容器/tmp目录中的内容,则可使用如下命令启动容器: 265 | 266 | ```shell 267 | docker run -volume-from 容器ID 镜像名称 # 容器ID是di一个容器的ID,镜像是第二个容器所使用的镜像。 268 | ``` 269 | 270 | 271 | 272 | ## WORKDIR 指定工作目录 273 | 274 | 格式为: 275 | 276 | - `WORKDIR /path/to/workdir` 277 | 278 | 切换目录指令,类似于cd命令,写在该指令后的`RUN`,`CMD`以及`ENTRYPOINT`指令都将该目录作为当前目录,并执行相应的命令。 279 | 280 | 281 | 282 | 283 | 284 | ## 其他 285 | 286 | Dockerfile还有一些其他的指令,例如STOPSINGAL、HEALTHCHECK、SHELL等。由于并不是很常用,本书不作赘述。有兴趣的读者可前往[https://docs.docker.com/engine/reference/builder/](https://docs.docker.com/engine/reference/builder/) 扩展阅读。 287 | 288 | 289 | 290 | ## CMD/ENTRYPOINT/RUN区别 291 | 292 | 参考: 293 | 294 | 295 | 296 | **拓展阅读** 297 | 298 | * Dockerfile官方文档:https://docs.docker.com/engine/reference/builder/#dockerfile-reference 299 | * Dockerfile最佳实践:https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#build-cache 300 | 301 | -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/09-实战:使用Dockerfile修改Nginx首页.md: -------------------------------------------------------------------------------- 1 | # 实战:使用Dockerfile修改Nginx首页 2 | 3 | 创建一个Dockerfile,内容如下: 4 | 5 | ```dockerfile 6 | FROM nginx 7 | RUN echo '

Spring Cloud与Docker微服务实战

' > /usr/share/nginx/html/index.html 8 | ``` 9 | 10 | -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/10-实战:使用Dockerfile在CentOS 7中安装Nginx.md: -------------------------------------------------------------------------------- 1 | # 第十章 实战:使用Dockerfile在CentOS 7中安装Nginx 2 | 3 | 基于CentOS 7镜像,在其中安装Nginx,并启动。 4 | 5 | **提示**:默认Nginx不在官方Yum仓库中,需要先安装RPMS仓库包,这样才能用Yum安装Nginx。安装RPMS包的命令如下: 6 | 7 | ```Shell 8 | rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 9 | ``` 10 | 11 | 12 | 13 | ## 答案 14 | 15 | ```dockerfile 16 | FROM centos:7 17 | RUN rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 18 | RUN yum -y install nginx 19 | RUN sed -i '1i\daemon off;' /etc/nginx/nginx.conf 20 | ENTRYPOINT nginx 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/11-实战:使用Dockerfile构建一个Spring Boot应用镜像.md: -------------------------------------------------------------------------------- 1 | # 第十一章 实战:使用Dockerfile构建一个Spring Boot应用镜像 2 | 有一个Java应用,在裸机中的启动命令是`java -jar xxx.jar` ,请将其制作成Docker镜像,并启动。 3 | 4 | 5 | 6 | ## 答案 7 | 8 | ```dockerfile 9 | # 基于哪个镜像 10 | FROM java:8 11 | 12 | # 将本地文件夹挂载到当前容器 13 | VOLUME /tmp 14 | 15 | # 拷贝文件到容器,也可以直接写成ADD xxxxx.jar /app.jar 16 | ADD xxxxx.jar app.jar /app.jar' 17 | 18 | # 声明需要暴露的端口 19 | EXPOSE 8761 20 | 21 | # 配置容器启动后执行的命令 22 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/12-实战:巩固-阅读常用软件的Dockerfile.md: -------------------------------------------------------------------------------- 1 | # 巩固-阅读常用软件的Dockerfile 2 | 3 | * Nginx: 4 | * Tomcat: 5 | * 关于Alpine Linux: 6 | 7 | 8 | -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/images/12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第2章-Dockerfile详解/images/12-1.png -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/images/13-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第2章-Dockerfile详解/images/13-2.png -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/images/13-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第2章-Dockerfile详解/images/13-3.png -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/images/docker-registry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第2章-Dockerfile详解/images/docker-registry.jpg -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/images/docker-vs-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第2章-Dockerfile详解/images/docker-vs-vm.png -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/images/docker-版本迭代计划.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第2章-Dockerfile详解/images/docker-版本迭代计划.png -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/images/nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第2章-Dockerfile详解/images/nexus.png -------------------------------------------------------------------------------- /docker/第2章-Dockerfile详解/images/镜像加速器.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第2章-Dockerfile详解/images/镜像加速器.png -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/13-使用Docker Hub管理镜像.md: -------------------------------------------------------------------------------- 1 | # 使用Docker Hub管理镜像 2 | 3 | Docker Hub是Docker官方维护的Docker Registry,上面存放着很多优秀的镜像。不仅如此,Docker Hub还提供认证、工作组结构、工作流工具、构建触发器等工具来简化我们的工作。 4 | 5 | 前文已经讲过,我们可使用`docker search` 命令搜索存放在Docker Hub中的镜像。本节我们来详细探讨Docker Hub的使用。 6 | 7 | 8 | 9 | 10 | 11 | ## 注册与登录 12 | 13 | Docker Hub的使用非常简单,只需注册一个Docker Hub账号,就可正常使用了。登录后,我们可看到Docker Hub的主页,如图所示。 14 | 15 | ![](images/13-2.png) 16 | 17 | 我们也可使用`docker login` 命令登录Docker Hub。输入该命令并按照提示输入账号和密码,即可完成登录。例如: 18 | 19 | ```shell 20 | $ docker login 21 | Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. 22 | Username: itmuch 23 | Password: 24 | Login Succeeded 25 | ``` 26 | 27 | 28 | 29 | 30 | 31 | ## 创建仓库 32 | 33 | 点击Docker Hub主页上的"Create Repository"按钮,按照提示填入信息即可创建一个仓库。 34 | 35 | ![](images/13-3.png) 36 | 37 | 如图,我们只需填入相关信息,并点击Create按钮,就可创建一个名为microservice-discovery-eureka的公共仓库。 38 | 39 | 40 | 41 | 42 | 43 | ## 推送镜像 44 | 45 | 下面我们来将前文构建的镜像推送到Docker Hub。使用以下命令即可,例如: 46 | 47 | ```shell 48 | docker push itmuch/microservice-discovery-eureka:0.0.1 49 | ``` 50 | 51 | 经过一段时间的等待,就可推送成功。这样,我们就可在Docker Hub查看已推送的镜像。 -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/14-使用Docker Registry管理Docker镜像.md: -------------------------------------------------------------------------------- 1 | # 使用Docker Registry管理镜像 2 | 3 | 很多场景下,我们需使用私有仓库管理Docker镜像。相比Docker Hub,私有仓库有以下优势: 4 | 5 | (1) 节省带宽,对于私有仓库中已有的镜像,无需从Docker Hub下载,只需从私有仓库中下载即可; 6 | 7 | (2) 更加安全; 8 | 9 | (3) 便于内部镜像的统一管理。 10 | 11 | 本节我们来探讨如何搭建、使用私有仓库。可使用docker-registry项目或者Docker Registry 2.0来搭建私有仓库,但docker-registry已被官方标记为过时,并且已有2年不维护了,不建议使用。 12 | 13 | 我们先用Docker Registry 2.0搭建一个私有仓库,然后将Docker镜像推送到私有仓库。 14 | 15 | 16 | 17 | 18 | 19 | ## 原理图 20 | 21 | ![](images/docker-registry.jpg) 22 | 23 | 24 | 25 | 26 | 27 | ## 搭建Docker Registry 2.0 28 | 29 | Docker Registry 2.0的搭建非常简单,只需执行以下命令即可新建并启动一个Docker Registry 2.0。 30 | 31 | ```shell 32 | docker run -d -p 5000:5000 --restart=always --name registry2 registry:2 33 | ``` 34 | 35 | 36 | 37 | 38 | 39 | ## 将镜像推送到Docker Registry 2.0 40 | 41 | 前文我们使用`docker push` 命令将镜像推送到了Docker Hub,现在我们将前文构建的itmuch/microservice-discovery-eureka:0.0.1推送到私有仓库。 42 | 43 | 只需指定私有仓库的地址,即可将镜像推送到私有仓库。 44 | 45 | ```shell 46 | docker push localhost:5000/itmuch/microservice-discovery-eureka:0.0.1 47 | ``` 48 | 49 | 执行以上命令,我们发现推送并没有成功,且提示以下内容: 50 | 51 | ``` 52 | The push refers to a repository [localhost:5000/itmuch/microservice-discovery-eureka] 53 | An image does not exist locally with the tag: localhost:5000/itmuch/microservice-discovery-eureka 54 | ``` 55 | 56 | 我们知道,Docker Hub是默认的Docker Registry,因此,itmuch/microservice-discovery-eureka:0.0.1相当于docker.io/itmuch/microservice-discovery-eureka:0.0.1。因此,要想将镜像推送到私有仓库,需要修改镜像标签,命令如下: 57 | 58 | ```shell 59 | docker tag itmuch/microservice-discovery-eureka:0.0.1 localhost:5000/itmuch/microservice-discovery-eureka:0.0.1 60 | ``` 61 | 62 | 修改镜像标签后,再次执行以下命令,即可将镜像推送到私有仓库。 63 | 64 | ```shell 65 | docker push localhost:5000/itmuch/microservice-discovery-eureka:0.0.1 66 | ``` 67 | 68 | 69 | 70 | 71 | 72 | ## TIPS 73 | 74 | (1) docker-registry的GitHub:[https://github.com/docker/docker-registry](https://github.com/docker/docker-registry) 75 | 76 | (2) Docker Registry 2.0的GitHub:[https://github.com/docker/distribution](https://github.com/docker/distribution) 77 | 78 | (3) 本节中“私有仓库”表示私有Docker Registry,并非Docker中仓库的概念。 79 | 80 | (4) Docker Registry 2.0需要Docker版本高于1.6.0。 81 | 82 | (5) 我们还可为私有仓库配置域名、SSL登录、认证等。限于篇幅,本书不作赘述。有兴趣的读者可参考笔者的开源书:。 83 | 84 | (6) Docker Registry 2.0能够满足我们大部分场景下的需求,但它不包含界面、用户管理、权限控制等功能。如果想要使用这些功能,可使用Docker Trusted Registry。 85 | -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/15-使用Nexus管理Docker镜像.md: -------------------------------------------------------------------------------- 1 | # 使用Nexus管理Docker镜像 2 | 3 | ## Nexus简介 4 | 5 | Nexus是一个多功能的仓库管理器,是企业常用的私有仓库服务器软件。目前常被用来作为Maven私服、Docker私服。本文基于`Nexus 3.5.2-01` 版本进行讲解。 6 | 7 | 8 | 9 | ## Nexus下载 10 | 11 | 前往: ,根据操作系统,下载对应操作系统下的安装包即可。 12 | 13 | 14 | 15 | ## 安装 16 | 17 | Nexus在不同系统中安装略有区别,但总体一致。下面以在Linux系统中的安装为例说明: 18 | 19 | * 创建一个Linux用户,例如:nexus 20 | 21 | ``` 22 | useradd nexus 23 | ``` 24 | 25 | * 解压Nexus安装包,为将解压后的文件设置权限,并修改属主为nexus用户 26 | 27 | ```shell 28 | chmod -R 755 * 29 | chown -R nexus:nexus * 30 | ``` 31 | 32 | * 将目录切换到`$NEXUS_HOME/nexus-3.5.2-01/bin` 目录 33 | 34 | * 需改`nexus.rc` 文件,将其内容改为: 35 | 36 | ```Shell 37 | run_as_user="nexus" 38 | ``` 39 | 40 | 表示使用nexus用户启动Nexus。 41 | 42 | * 如提示文件限制,可参考博文: 进行修改。 43 | 44 | * 执行如下命令,查看Nexus为我们提供哪些命令。 45 | 46 | ``` 47 | ./nexus --help 48 | ``` 49 | 50 | 可显示类似如下的内容: 51 | 52 | ``` 53 | Usage: ./nexus {start|stop|run|run-redirect|status|restart|force-reload} 54 | ``` 55 | 56 | * 指定如下命令,即可启动Nexus 57 | 58 | ``` 59 | ./nexus start 60 | ``` 61 | 62 | 稍等片刻,Nexus即可成功启动。 63 | 64 | 65 | 66 | ## 账户 67 | 68 | Nexus提供了默认的管理员账户,账号密码分别是admin/admin123。用户可自行修改该默认账号密码。 69 | 70 | 71 | 72 | ## 创建Docker仓库 73 | 74 | * 访问 并登录 75 | * 点击“Create repository”按钮,创建仓库。Nexus支持多种仓库类型,例如:maven、npm、docker等。本文创建一个docker仓库。一般来说,对于特定的仓库类型(例如docker),细分了三类,分别是proxy、hosted、group,含义如下: 76 | * hosted,本地代理仓库,通常我们会部署自己的构件到这一类型的仓库,可以push和pull。 77 | * proxy,代理的远程仓库,它们被用来代理远程的公共仓库,如maven中央仓库,只能pull。 78 | * group,仓库组,用来合并多个hosted/proxy仓库,通常我们配置maven依赖仓库组,只能pull。 79 | * 本文创建一个**hosted**类型的仓库 80 | * 配置仓库,如图,填入如下结果:![](images/nexus.png) 81 | * 这样,仓库就创建完毕了。 82 | 83 | 84 | 85 | ## Docker配置 86 | 87 | 下面,我们需要为Docker指定使用Nexus仓库。 88 | 89 | * 修改`/etc/docker/daemon.json` ,在其中添加类似如下的内容。 90 | 91 | ``` 92 | { 93 | "insecure-registries" : [ 94 | "192.168.1.101:8082" 95 | ] 96 | ... 97 | } 98 | ``` 99 | 100 | * 重启Docker 101 | 102 | 103 | 104 | ## 登录私有仓库 105 | 106 | ```shell 107 | docker login 192.168.1.101:8082 108 | ``` 109 | 110 | 即可登录私有仓库。然后,我们就可进行pull、push操作了。 111 | 112 | 113 | 114 | 115 | 116 | ## 容器启动Nexus 117 | 118 | 地址: 119 | 120 | ```shell 121 | docker run -d -p 8081:8081 --name nexus sonatype/nexus3 122 | ``` 123 | 124 | 为启动的容器映射端口: 125 | 126 | -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/images/12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第3章-Docker镜像管理/images/12-1.png -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/images/13-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第3章-Docker镜像管理/images/13-2.png -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/images/13-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第3章-Docker镜像管理/images/13-3.png -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/images/docker-registry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第3章-Docker镜像管理/images/docker-registry.jpg -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/images/docker-vs-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第3章-Docker镜像管理/images/docker-vs-vm.png -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/images/docker-版本迭代计划.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第3章-Docker镜像管理/images/docker-版本迭代计划.png -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/images/nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第3章-Docker镜像管理/images/nexus.png -------------------------------------------------------------------------------- /docker/第3章-Docker镜像管理/images/镜像加速器.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第3章-Docker镜像管理/images/镜像加速器.png -------------------------------------------------------------------------------- /docker/第4章-Docker工具/16-使用Maven插件构建Docker镜像.md: -------------------------------------------------------------------------------- 1 | # 第十六章 使用Maven插件构建Docker镜像 2 | 3 | 我们知道,Maven是一个强大的项目管理与构建工具。如果可以使用Maven构建Docker镜像,那么我们的工作就能得到进一步的简化。 4 | 5 | 经过调研,以下几款Maven的Docker插件进入笔者视野,如表13-1所示。 6 | 7 | | 插件名称 | 官方地址 | 8 | | ------------------- | ---------------------------------------- | 9 | | docker-maven-plugin | https://github.com/spotify/docker-maven-plugin | 10 | | docker-maven-plugin | https://github.com/fabric8io/docker-maven-plugin | 11 | | docker-maven-plugin | https://github.com/bibryam/docker-maven-plugin | 12 | 13 | 表13-1 Maven的Docker插件列表 14 | 15 | 笔者从各项目的功能性、文档易用性、更新频率、社区活跃度、Stars等几个纬度考虑,选用了第一款。这是一款由Spotify公司开发的Maven插件。 16 | 17 | 下面我们来详细探讨如何使用Maven插件构建Docker镜像。 18 | 19 | 20 | 21 | 22 | 23 | ## 快速入门 24 | 25 | 以项目`microservice-discovery-eureka` 为例。 26 | 27 | (1) 在pom.xml中添加Maven的Docker插件。 28 | 29 | ```xml 30 | 31 | com.spotify 32 | docker-maven-plugin 33 | 0.4.13 34 | 35 | itmuch/microservice-discovery-eureka:0.0.1 36 | java 37 | ["java", "-jar", "/${project.build.finalName}.jar"] 38 | 39 | 40 | / 41 | ${project.build.directory} 42 | ${project.build.finalName}.jar 43 | 44 | 45 | 46 | 47 | ``` 48 | 简要说明一下插件的配置: 49 | 50 | ① imageName:用于指定镜像名称,其中itmuch是仓库名称,microservice-discovery-eureka是镜像名称,0.0.1是标签名称。 51 | 52 | ② baseImage:用于指定基础镜像,类似于Dockerfile中的FROM指令。 53 | 54 | ③ entrypoint:类似于Dockerfile的ENTRYPOINT指令。 55 | 56 | ④ resources.resource.directory:用于指定需要复制的根目录,${project.build.directory}表示target目录。 57 | 58 | ⑤ resources.resource.include:用于指定需要复制的文件。${project.build.finalName}.jar指的是打包后的jar包文件。 59 | 60 | (2) 执行以下命令,构建Docker镜像。 61 | 62 | ```shell 63 | mvn clean package docker:build 64 | ``` 65 | 我们会发现终端输出类似于如下的内容: 66 | 67 | ```shell 68 | [INFO] Building image itmuch/microservice-discovery-eureka:0.0.1 69 | Step 1 : FROM java 70 | ---> 861e95c114d6 71 | Step 2 : ADD /microservice-discovery-eureka-0.0.1-SNAPSHOT.jar // 72 | ---> 035a03f5b389 73 | Removing intermediate container 2b0e70056f1d 74 | Step 3 : ENTRYPOINT java -jar /microservice-discovery-eureka-0.0.1-SNAPSHOT.jar 75 | ---> Running in a0149704b949 76 | ---> eb96ca1402aa 77 | Removing intermediate container a0149704b949 78 | Successfully built eb96ca1402aa 79 | ``` 80 | 81 | 由以上日志可知,我们已成功构建了一个Docker镜像。 82 | 83 | (3)执行 `docker images` 命令,即可查看刚刚构建的镜像。 84 | 85 | ``` 86 | REPOSITORY TAG IMAGE ID CREATED SIZE 87 | itmuch/microservice-discovery-eureka 0.0.1 eb96ca1402aa 39 seconds ago 685 MB 88 | ``` 89 | (4) 启动镜像 90 | 91 | ```shell 92 | docker run -d -p 8761:8761 itmuch/microservice-discovery-eureka:0.0.1 93 | ``` 94 | 95 | 我们会发现该Docker镜像会很快地启动 96 | 97 | (5) 访问测试 98 | 99 | 访问[http://Docker宿主机IP:8761](http://Docker宿主机IP:8761) ,能够看到Eureka Server的首页。 100 | 101 | 102 | 103 | 104 | 105 | ## 插件读取Dockerfile进行构建 106 | 107 | 之前的示例,我们直接在pom.xml中设置了一些构建的参数。很多场景下,我们希望使用Dockerfile更精确、有可读性地构建镜像。 108 | 109 | (1) 首先我们在`/microservice-discovery-eureka/src/main/docker` 目录下,新建一个Dockerfile文件,例如: 110 | 111 | ```dockerfile 112 | FROM java:8 113 | VOLUME /tmp 114 | ADD microservice-discovery-eureka-0.0.1-SNAPSHOT.jar app.jar 115 | RUN bash -c 'touch /app.jar' 116 | EXPOSE 9000 117 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] 118 | ``` 119 | 120 | (2) 修改pom.xml 121 | 122 | ```xml 123 | 124 | com.spotify 125 | docker-maven-plugin 126 | 0.4.13 127 | 128 | itmuch/microservice-discovery-eureka:0.0.2 129 | ${project.basedir}/src/main/docker 130 | 131 | 132 | / 133 | ${project.build.directory} 134 | ${project.build.finalName}.jar 135 | 136 | 137 | 138 | 139 | ``` 140 | 141 | 可以看到,我们不再指定baseImage和entrypoint,而是使用dockerDirectory指定Dockerfile所在的路径。这样,我们就可以使用Dockerfile构建Docker镜像了。 142 | 143 | 144 | 145 | 146 | 147 | ## 将插件绑定在某个phase执行 148 | 149 | 很多场景下,我们有这样的需求,执行例如`mvn clean package` 时,插件就自动为我们构建Docker镜像。要想实现这点,我们只需将插件的goal绑定在某个phase即可。 150 | 151 | phase和goal可以这样理解:maven命令格式是:`mvn phase:goal` ,例如`mvn package docker:build` 。那么,package和docker都是phase,build则是goal 。示例: 152 | 153 | ```xml 154 | 155 | com.spotify 156 | docker-maven-plugin 157 | 0.4.13 158 | 159 | 160 | build-image 161 | package 162 | 163 | build 164 | 165 | 166 | 167 | 168 | itmuch/microservice-discovery-eureka:0.0.3 169 | java 170 | ["java", "-jar", "/${project.build.finalName}.jar"] 171 | 172 | 173 | / 174 | ${project.build.directory} 175 | ${project.build.finalName}.jar 176 | 177 | 178 | 179 | 180 | ``` 181 | 182 | 由配置可知,我们只需添加如下配置: 183 | 184 | ```xml 185 | 186 | 187 | build-image 188 | package 189 | 190 | build 191 | 192 | 193 | 194 | ``` 195 | 196 | 就可将插件绑定在package这个phase上。也就是说,用户只需执行`mvn package` ,就会自动执行`mvn docker:build` 。当然,读者也可按照需求,将插件绑定到其他的phase。 197 | 198 | 199 | 200 | 201 | 202 | ## 推送镜像 203 | 204 | 前文我们使用`docker push` 命令实现了镜像的推送,我们也可使用Maven插件推送镜像。我们不妨使用Maven插件推送一个Docker镜像到Docker Hub。 205 | 206 | (1) 修改Maven的全局配置文件setttings.xml,在其中添加以下内容,配置Docker Hub的用户信息。 207 | 208 | ```xml 209 | 210 | docker-hub 211 | 你的DockerHub用户名 212 | 你的DockerHub密码 213 | 214 | 你的DockerHub邮箱 215 | 216 | 217 | ``` 218 | 219 | (2) 修改pom.xml,示例: 220 | 221 | ```xml 222 | 223 | com.spotify 224 | docker-maven-plugin 225 | 0.4.13 226 | 227 | itmuch/microservice-discovery-eureka:0.0.4 228 | java 229 | ["java", "-jar", "/${project.build.finalName}.jar"] 230 | 231 | 232 | / 233 | ${project.build.directory} 234 | ${project.build.finalName}.jar 235 | 236 | 237 | 238 | 239 | docker-hub 240 | 241 | 242 | ``` 243 | 244 | 如上,添加serverId段落,并引用settings.xml中的server的id即可。 245 | 246 | (3) 执行以下命令,添加pushImage的标识,表示推送镜像。 247 | 248 | ```shell 249 | mvn clean package docker:build -DpushImage 250 | ``` 251 | 252 | 经过一段时间的等待,我们会发现Docker镜像已经被push到Docker Hub了。同理,我们也可推送镜像到私有仓库,只需要将imageName指定成类似于如下的形式即可: 253 | 254 | ```xml 255 | localhost:5000/itmuch/microservice-discovery-eureka:0.0.4 256 | ``` 257 | 258 | 259 | 260 | 261 | 262 | **TIPS** 263 | 264 | (1) 以上示例中,我们是通过imageName指定镜像名称和标签的,例如: 265 | 266 | ```xml 267 | itmuch/microservice-discovery-eureka:0.0.4 268 | ``` 269 | 270 | 我们也可借助imageTags元素更为灵活地指定镜像名称和标签,例如: 271 | 272 | ```xml 273 | 274 | itmuch/microservice-discovery-eureka 275 | 276 | 0.0.5 277 | latest 278 | 279 | ... 280 | 281 | ``` 282 | 283 | 这样就可为同一个镜像指定两个标签。 284 | 285 | (2) 我们也可在执行构建命令时,使用dockerImageTags参数指定标签名称,例如: 286 | 287 | ```shell 288 | mvn clean package docker:build -DpushImageTags -DdockerImageTags=latest -DdockerImageTags=another-tag 289 | ``` 290 | 291 | (3) 如需重复构建相同标签名称的镜像,可将forceTags设为true,这样就会覆盖构建相同标签的镜像。 292 | 293 | ```xml 294 | 295 | 296 | true 297 | 298 | ``` 299 | 300 | 301 | 302 | 303 | 304 | 305 | ## 拓展阅读 306 | 307 | (1) Spotify是全球最大的正版流媒体音乐服务平台。 -------------------------------------------------------------------------------- /docker/第4章-Docker工具/17-小作业.md: -------------------------------------------------------------------------------- 1 | # 第十七章 小作业 2 | 3 | 作业要求: 4 | 5 | * 基于CentOS 7,编写自己的Nginx镜像; 6 | * 让Nginx读取宿主机中的`/opt/conf/nginx.conf` ,该配置文件将nginx的端口设为81; 7 | * 访问Nginx首页时,Nginx会读取宿主机`/opt/html` 目录下的`index.html` ; 8 | * 将该镜像push到Docker Registry或者Nexus中。 9 | 10 | 11 | 注:如宿主机不存在/opt目录(例如Window 7),可使用`C:\` 代替。 12 | 13 | 14 | 15 | ## 准备工作 16 | 17 | 1. 在宿主机中准备好目录 18 | 19 | ``` 20 | mkdir -p /opt/conf /opt/html 21 | ``` 22 | 23 | 2. 启动一个NGINX容器(官方NGINX容器即可) 24 | 25 | 3. 使用命令拷贝容器内部的`/etc/nginx/conf.d/default.conf` 文件,到宿主机的/opt目录,命名为nginx.conf 26 | 27 | ```Shell 28 | docker cp 容器ID:/etc/nginx/conf.d/default.conf /opt/conf/nginx.conf 29 | ``` 30 | 31 | 4. 修改宿主机中的`/opt/nginx.conf` ,找到类似如下的内容,将其改为81。 32 | 33 | ``` nginx 34 | listen 80; # 改为81 35 | ``` 36 | 37 | 5. 在/opt/html目录下准备一个文件,例如:`index.html` 。 38 | 39 | 40 | 41 | 42 | 43 | ## 答案 44 | 45 | 1. 先制作一个基础镜像,Dockerfile如下: 46 | 47 | ```dockerfile 48 | FROM centos:7 49 | RUN rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 50 | RUN yum -y install nginx 51 | RUN sed -i '1i\daemon off;' /etc/nginx/nginx.conf 52 | ENTRYPOINT nginx 53 | ``` 54 | 使用`docker build -t mynginx .` 构建镜像。 55 | 56 | 2. 在mynginx的基础上,制作一个新的镜像,内容如下: 57 | 58 | ```dockerfile 59 | FROM mynginx 60 | VOLUME /etc/nginx/conf.d/ 61 | VOLUME /usr/share/nginx/html 62 | ``` 63 | 64 | 使用`docker build -t nginx-haha .` 构建镜像。 65 | 66 | 3. 使用如下命令,启动nginx-haha。 67 | 68 | ```shell 69 | docker run -p 80:81 -v /opt/conf:/etc/nginx/conf.d/ -v /opt/html:/usr/share/nginx/html nginx-haha 70 | ``` 71 | 72 | ​ -------------------------------------------------------------------------------- /docker/第4章-Docker工具/18-Docker可视化管理工具.md: -------------------------------------------------------------------------------- 1 | # Docker可视化管理工具 2 | 3 | ## DockerUI(ui for Docker) 4 | 5 | 官方GitHub: 6 | 7 | 项目已废弃,现在转投Portainer项目。 8 | 9 | 10 | 11 | ## Portainer 12 | 13 | 简介:Portainer是一个轻量级的管理界面,可以让您轻松地管理不同的Docker环境(Docker主机或Swarm集群)。Portainer提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和操作、登录用户管理和控制等功能。功能十分全面,基本能满足中小型单位对容器管理的全部需求。 14 | 15 | 官方GitHub: 16 | 17 | 使用: 18 | 19 | ``` 20 | docker run -d --privileged -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /opt/portainer:/data portainer/portainer 21 | ``` 22 | 23 | 如开启了SELinux,可执行如下命令启动: 24 | 25 | ``` 26 | docker run -d --privileged -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /opt/portainer:/data portainer/portainer 27 | ``` 28 | 29 | 官方文档: 30 | 31 | 32 | 33 | ## Kitematic 34 | 35 | 简介:Kitematic是一个Docker GUI。 36 | 37 | 官方GitHub: 38 | 39 | 使用:演示 40 | 41 | 42 | 43 | ## Shipyard 44 | 45 | 简介:Shipyard 是一个基于 Web 的 Docker 管理工具,支持多 host,可以把多个 Docker host 上的 containers 统一管理;可以查看 images,甚至 build images;并提供 RESTful API 等。 46 | 47 | 官方GitHub: 48 | 49 | 安装: 50 | 51 | ``` 52 | curl -s https://shipyard-project.com/deploy | bash -s 53 | ``` 54 | 55 | 展示所有参数: 56 | 57 | ``` 58 | curl -s https://shipyard-project.com/deploy | bash -s -- -h 59 | ``` 60 | 61 | 使用:访问 ,输入账号/密码:admin/shipyard即可访问Shipyard。 62 | 63 | 官方文档: 64 | 65 | 66 | 67 | ## 各种可视化界面的比较 68 | 69 | 参考: -------------------------------------------------------------------------------- /docker/第4章-Docker工具/images/12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第4章-Docker工具/images/12-1.png -------------------------------------------------------------------------------- /docker/第4章-Docker工具/images/13-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第4章-Docker工具/images/13-2.png -------------------------------------------------------------------------------- /docker/第4章-Docker工具/images/13-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第4章-Docker工具/images/13-3.png -------------------------------------------------------------------------------- /docker/第4章-Docker工具/images/docker-registry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第4章-Docker工具/images/docker-registry.jpg -------------------------------------------------------------------------------- /docker/第4章-Docker工具/images/docker-vs-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第4章-Docker工具/images/docker-vs-vm.png -------------------------------------------------------------------------------- /docker/第4章-Docker工具/images/docker-版本迭代计划.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第4章-Docker工具/images/docker-版本迭代计划.png -------------------------------------------------------------------------------- /docker/第4章-Docker工具/images/nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第4章-Docker工具/images/nexus.png -------------------------------------------------------------------------------- /docker/第4章-Docker工具/images/镜像加速器.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第4章-Docker工具/images/镜像加速器.png -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/19-Docker数据持久化.md: -------------------------------------------------------------------------------- 1 | # Docker数据持久化 2 | 3 | 容器中数据持久化主要有两种方式: 4 | 5 | * 数据卷(Data Volumes) 6 | * 数据卷容器(Data Volumes Dontainers) 7 | 8 | 9 | 10 | ## 数据卷 11 | 12 | 数据卷是一个可供一个或多个容器使用的特殊目录,可以绕过UFS(Unix File System)。 13 | 14 | * 数据卷可以在容器之间共享和重用 15 | * 对数据卷的修改会立马生效 16 | * 对数据卷的更新,不会影响镜像 17 | * 数据卷默认会一直存在,即使容器被删除 18 | * 一个容器可以挂载多个数据卷 19 | 20 | **注意**:数据卷的使用,类似于 Linux 下对目录或文件进行 mount。 21 | 22 | 23 | 24 | ### 创建数据卷 25 | 26 | 示例: 27 | 28 | ```shell 29 | docker run --name nginx-data -v /mydir nginx 30 | ``` 31 | 32 | 执行如下命令即可查看容器构造的详情: 33 | 34 | ```Shell 35 | docker inspect 容器ID 36 | ``` 37 | 38 | 由测试可知: 39 | 40 | * Docker会自动生成一个目录作为挂载的目录。 41 | 42 | 43 | * **即使容器被删除,宿主机中的目录也不会被删除。** 44 | 45 | 46 | 47 | 48 | 49 | ### 删除数据卷 50 | 51 | 数据卷是被设计来持久化数据的,因此,删除容器并不会删除数据卷。如果想要在删除容器时同时删除数据卷,可使用如下命令: 52 | 53 | ```shell 54 | docker rm -v 容器ID 55 | ``` 56 | 57 | 这样既可在删除容器的同时也将数据卷删除。 58 | 59 | 60 | 61 | ### 挂载宿主机目录作为数据卷 62 | 63 | ```shell 64 | docker run --name nginx-data2 -v /host-dir:/container-dir nginx 65 | ``` 66 | 67 | 这样既可将宿主机的/host-dir路径加载到容器的/container-dir中。 68 | 69 | 需要注意的是: 70 | 71 | * 宿主机路径**尽量设置**绝对路径——如果使用相对路径会怎样? 72 | * 测试给答案 73 | * 如果宿主机路径不存在,Docker会自动创建 74 | 75 | **TIPS** 76 | 77 | Dockerfile暂时不支持这种形式。 78 | 79 | 80 | 81 | ### 挂载宿主机文件作为数据卷 82 | 83 | ```Shell 84 | docker run --name nginx-data3 -v /文件路径:/container路径 nginx 85 | ``` 86 | 87 | 88 | 89 | ### 指定权限 90 | 91 | 默认情况下,挂载的权限是读写权限。也可使用`:ro` 参数指定只读权限。 92 | 93 | 示例: 94 | 95 | ```Shell 96 | docker run --name nginx-data4 -v /host-dir:/container-dir:ro nginx 97 | ``` 98 | 99 | 这样,在容器中就只能读取/container-dir中的文件,而不能修改了。 100 | 101 | 102 | 103 | 104 | 105 | ## 数据卷容器 106 | 107 | 如果有数据需要在多个容器之间共享,此时可考虑使用数据卷容器。 108 | 109 | 创建数据卷容器: 110 | 111 | ```dockerfile 112 | docker run --name nginx-volume -v /data nginx 113 | ``` 114 | 115 | 在其他容器中使用`-volumes-from` 来挂载nginx-volume容器中的数据卷。 116 | 117 | ```dockerfile 118 | docker run --name v1 --volumes-from nginx-volume nginx 119 | docker run --name v2 --volumes-from nginx-volume nginx 120 | ``` 121 | 122 | 这样: 123 | 124 | * v1、v2两个容器即可共享nginx-volume这个容器中的文件。 125 | * 即使nginx-volume停止,也不会有任何影响。 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/images/12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第5章-Docker数据持久化/images/12-1.png -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/images/13-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第5章-Docker数据持久化/images/13-2.png -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/images/13-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第5章-Docker数据持久化/images/13-3.png -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/images/docker-registry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第5章-Docker数据持久化/images/docker-registry.jpg -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/images/docker-vs-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第5章-Docker数据持久化/images/docker-vs-vm.png -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/images/docker-版本迭代计划.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第5章-Docker数据持久化/images/docker-版本迭代计划.png -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/images/nexus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第5章-Docker数据持久化/images/nexus.png -------------------------------------------------------------------------------- /docker/第5章-Docker数据持久化/images/镜像加速器.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第5章-Docker数据持久化/images/镜像加速器.png -------------------------------------------------------------------------------- /docker/第6章-Docker网络/20-端口映射.md: -------------------------------------------------------------------------------- 1 | # 端口映射 2 | 3 | 在前面的内容中,我们很多地方使用了-p参数来实现端口映射。本节我们来详细讲解Docker中的端口映射。 4 | 5 | ## 随机映射:-P 6 | 7 | 当启动时使用-P参数时,即可让Docker随机映射一个端口到容器内部开放的端口 8 | 9 | ```shell 10 | docker run -P nginx 11 | ``` 12 | 13 | ## 指定端口映射:-p 14 | 15 | 指定端口映射有如下几种格式: 16 | 17 | * ip:hostPort:containerPort:映射到指定IP的指定端口 18 | * ip::containerPort:映射到指定IP的随机端口 19 | * hostPort:containerPort:映射到宿主机所有IP的指定端口 20 | * containerPort:映射到宿主机所有IP的随机端口 21 | 22 | ## 查看端口映射 23 | 24 | 有多种方式可以查看端口映射的详情。 25 | 26 | * 方法1: 27 | 28 | ``` 29 | docker ps 30 | ``` 31 | 32 | * 方法2: 33 | 34 | ``` 35 | docker port 容器ID 36 | ``` 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /docker/第6章-Docker网络/21-遗留网络.md: -------------------------------------------------------------------------------- 1 | ## 遗留特性:容器互联 2 | 3 | 端口映射实现了外部与容器的网络通信,下面我们来探讨容器之间如何通信。使用`--link` 参数即可实现容器之间的互联。该参数的格式为:`--link name:alias` ,其中,name是容器的名称,alias则是这个连接的别名。 4 | 5 | ``` 6 | docker run --link nginx:nginx eureka # 使用eureka镜像启动容器,并将其连接上nginx这个容器。 7 | ``` 8 | 9 | 注:该特性未来可能被删除,不做赘述。相关文档: 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docker/第6章-Docker网络/24-默认bridge网络中配置DNS.md: -------------------------------------------------------------------------------- 1 | # 默认bridge网络中配置DNS 2 | 3 | 本节描述如何在Docker默认网桥中配置容器DNS。 当您安装Docker时,就会自动创建一个名为`bridge` 的桥接网络。 4 | 5 | > **注意** : [Docker网络功能](https://docs.docker.com/engine/userguide/networking/) 允许您创建除默认网桥之外的用户自定义网络。 有关用户自定义网络中DNS配置的更多信息,请参阅[Docker嵌入式DNS](https://docs.docker.com/engine/userguide/networking/configure-dns/) 部分。 6 | 7 | Docker如何为每个容器提供主机名和DNS配置,而无需在构建自定义Docker镜像时在内部写入主机名?它的诀窍是利用可以写入新信息的虚拟文件,在容器内覆盖三个关键的`/etc` 文件。 你可以通过在一个容器中运行`mount` 来看到这一点: 8 | 9 | ``` 10 | root@f38c87f2a42d:/# mount 11 | 12 | ... 13 | /dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ... 14 | /dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ... 15 | /dev/disk/by-uuid/1fec...ebdf on /etc/resolv.conf type ext4 ... 16 | ... 17 | ``` 18 | 19 | 这样一来,Docker可以让宿主机在稍后通过DHCP接收到新的配置后,使所有容器中的`resolv.conf` 保持最新状态。 Docker在容器中维护这些文件的具体细节可能会可能会随着Docker版本的演进而改变,因此您不该自己管理/etc文件,而应该用以下Docker选项。 20 | 21 | 四个不同的选项会影响容器域名服务。 22 | 23 | | 参数 | 描述 | 24 | | -------------------------------------- | ---------------------------------------- | 25 | | `-h HOSTNAME` or `--hostname=HOSTNAME` | 设置容器的主机名。 该设置的值将会被写入`/etc/hostname` ;写入`/etc/hosts` **作为容器的面向主机IP地址的名称(笔者按:在/etc/hosts里添加一条记录,IP是宿主机可以访问的IP,host就是你设置的host)**,并且是容器内部`/bin/bash` 在其提示符下显示的名称。 但主机名不容易从容器外面看到。 它不会出现在`docker ps` 或任何其他容器的`/etc/hosts` 文件中。 | 26 | | `--link=CONTAINER_NAME`or `ID:ALIAS` | 在`run` 容器时使用此选项为新容器的`/etc/hosts` 添加了一个名为`ALIAS`的额外条目,指向由`CONTAINER_NAME_or_ID`标识的`CONTAINER_NAME_or_ID`的IP地址。这使得新容器内的进程可以连接到主机名`ALIAS` 而不必知道其IP。 `--link=`选项将在下面进行更详细的讨论。 因为Docker可以在重新启动时为链接的容器分配不同的IP地址,Docker会更新收件人容器的`/etc/hosts` 文件中的`ALIAS`条目。 | 27 | | `--dns=IP_ADDRESS...` | 在容器的`/etc/resolv.conf`文件添加`nameserver` 行,IP地址为指定IP。 容器中的进程在如果需要访问`/etc/hosts` 里的主机名,就会连接到这些IP地址的53端口,寻找名称解析服务。 | 28 | | `--dns-search=DOMAIN...` | 通过在容器的`/etc/resolv.conf `写入`search` 行,在容器内使用裸不合格的主机名时搜索的域名。 当容器进程尝试访问`host` 并且搜索域`example.com` 被设置时,例如,DNS逻辑不仅将查找`host` ,还将查找`host.example.com` 。使用`--dns-search=.` 如果您不想设置搜索域。 | 29 | | `--dns-opt=OPTION...` | 通过将`options` 行写入容器的`/etc/resolv.conf` 设置DNS解析器使用的选项。有关有效选项的列表,请参阅`resolv.conf`文档 | 30 | 31 | 在没有`--dns=IP_ADDRESS...` , `--dns-search=DOMAIN...`或`--dns-opt=OPTION...`选项的情况下,**Docker使每个容器的`/etc/resolv.conf` 看起来像宿主机的`/etc/resolv.conf`** 。当创建容器的`/etc/resolv.conf` ,Docker daemon会从主机的原始文件中过滤掉所有localhost IP地址`nameserver` 条目。 32 | 33 | 过滤是必要的,因为主机上的所有localhost地址都不可从容器的网络中访问。 过滤之后,如果容器的`/etc/resolv.conf` 文件中没有更多的`nameserver` 条目,Docker daemon会将Google DNS名称服务器(8.8.8.8和8.8.4.4)添加到容器的DNS配置中。 如果守护进程启用了IPv6,则也会添加公共IPv6 Google DNS名称服务器(2001:4860:4860::8888 和 2001:4860:4860::8844)。 34 | 35 | > **注意** :如果您需要访问主机的localhost解析器,则必须在主机上修改DNS服务,以便侦听从容器内可访问的non-localhost地址。 36 | 37 | 您可能会想知道宿主机的`/etc/resolv.conf` 文件发生了什么变化。 `docker daemon` 有一个文件更改通知程序,它将监视主机DNS配置的更改。 38 | 39 | > **注意** :文件更改通知程序依赖于Linux内核的inotify功能。由于此功能目前与overlay文件系统驱动不兼容,因此使用“overlay”的Docker daemon将无法利用`/etc/resolv.conf` 自动更新的功能。 40 | 41 | 当宿主机文件更改时,所有`resolv.conf` 与主机匹配的**停止的容器将立即更新到最新的主机配置**。 当宿主机配置更改时,**运行的容器将需要停止并开始接收主机更改**,这是由于缺少设备,以确保在容器运行时对`resolv.conf` 文件的原子写入。 如果容器修改了默认的`resolv.conf` 文件,则不会替换该文件,因为如果替换,将会覆盖容器执行的更改。 如果选项( `--dns` , `--dns-search` 或`--dns-opt` )已被用于修改默认的主机配置,则更换主机的`/etc/resolv.conf` 也不会发生。 42 | 43 | > **注意** :对于在Docker 1.5.0中实现`/etc/resolv.conf` 更新功能之前创建的容器:当主机`resolv.conf`文件更改时,这些容器将**不会**收到更新。 只有使用Docker 1.5.0及以上版本创建的容器才能使用此自动更新功能。 44 | 45 | 46 | 47 | ## 原文 48 | 49 | 50 | 51 | 52 | 53 | ## 拓展阅读 54 | 55 | Docker存储驱动的选择: -------------------------------------------------------------------------------- /docker/第6章-Docker网络/25-用户定义网络中的内嵌DNS服务器.md: -------------------------------------------------------------------------------- 1 | # 用户定义网络中的内嵌DNS服务器 2 | 3 | 本节中的信息涵盖用户自定义网络中的容器的内嵌DNS服务器操作。连接到用户自定义网络的容器的DNS lookup与连接到默认`bridge` 网络的容器的工作机制不同。 4 | 5 | > **注意** :为了保持向后兼容性, 默认` bridge` 网络的DNS配置保持不变, 有关默认网桥中DNS配置的详细信息,请参阅[默认网桥中的DNS](https://docs.docker.com/engine/userguide/networking/default_network/configure-dns/) 。 6 | 7 | 从Docker 1.10开始,Docker daemon实现了一个内嵌的DNS服务器,它为任何使用有效`name` 、`net-alias` 或使用`link` 别名所创建的容器提供内置的服务发现能力。 Docker如何管理容器内DNS配置的具体细节可随着Docker版本的改变而改变。 所以你不应该自己管理容器内的`/etc/hosts` 、`/etc/resolv.conf` 等文件,而是使用以下的Docker选项。 8 | 9 | 影响容器域名服务的各种容器选项。 10 | 11 | | `--name=CONTAINER-NAME` | 使用`--name `配置的容器名称用于发现用户自定义网络中的容器。 内嵌DNS服务器维护容器名称及其IP地址(在容器连接的网络上)之间的映射。 | 12 | | ----------------------------- | ---------------------------------------- | 13 | | `--network-alias=ALIAS` | 除如上所述的`--name` 以外,容器可使用用户自定义网络中的一个或多个`--network-alias` (或`docker network connect` 命令中的`--alias` 选项)发现。 内嵌DNS服务器维护特定用户自定义网络中所有容器别名及IP之间的映射。 通过在 `docker network connect` 命令中使用`--alias` 选项,容器可在不同的网络中具有不同的别名。 | 14 | | `--link=CONTAINER_NAME:ALIAS` | 在`run` 容器时使用此选项为嵌入式DNS提供了一个名为`ALIAS` 的额外条目,指向由`CONTAINER_NAME` 标识的IP地址。 当使用`--link` 时,嵌入式DNS将确保只在使用了`--link` 选项的容器上进行本地化查找。 这允许新容器内的进程连接到容器,而不必知道其名称或IP。 | 15 | | `--dns=[IP_ADDRESS...]` | 如果嵌入式DNS服务器无法从容器中解析名称、解析请求,嵌入式DNS服务器将使用`--dns` 选项传递的IP地址转发DNS查询。 这些`--dns` IP地址由嵌入式DNS服务器管理,不会在容器的`/etc/resolv.conf` 文件中更新。 | 16 | | `--dns-search=DOMAIN...` | 当容器内使用主机名不合格时所设置的域名。这些`--dns-search` 选项由嵌入式DNS服务器管理,不会在容器的`/etc/resolv.conf` 文件中更新。当容器进程尝试访问`host` 并且搜索域 `example.com`被设置时,例如,DNS逻辑不仅将查找`host` ,还将查找`host.example.com` 。 | 17 | | `--dns-opt=OPTION...` | 设置DNS解析器使用的选项。 这些选项由嵌入式DNS服务器管理,不会在容器的`/etc/resolv.conf` 文件中更新。有关有效选项的列表,请参阅`resolv.conf`文档。 | 18 | 19 | 20 | 21 | 在没有`--dns=IP_ADDRESS...` ,`--dns-search=DOMAIN...` 或`--dns-opt=OPTION...` 选项的情况下,**Docker使用宿主机的`/etc/resolv.conf`** ( `docker daemon` 运行的地方)。 在执行此操作时,damon会从宿主机的原始文件中过滤出所有localhost IP地址`nameserver` 条目。 22 | 23 | 过滤是必要的,因为宿主机上的所有localhost地址都不可从容器的网络中访问。过滤之后,如果容器的`/etc/resolv.conf` 文件中没有更多的`nameserver` 条目,daemon会将公共Google DNS名称服务器(8.8.8.8和8.8.4.4)添加到容器的DNS配置中。 如果daemon启用了IPv6,则也会添加公共IPv6 Google DNS名称服务器(2001:4860:4860::8888 以及 2001:4860:4860::8844)。 24 | 25 | > **注意** :如果您需要访问宿主机的localhost解析器,则必须修改宿主机上的DNS服务,以便侦听从容器内可访问的non-localhost地址。 26 | 27 | > **注意** :DNS服务器始终为`127.0.0.11` 。 28 | 29 | 30 | 31 | ## 原文 32 | 33 | 34 | 35 | 36 | 37 | ## 参考&拓展阅读 38 | 39 | Docker内置DNS: 40 | 41 | Dns: http://blog.csdn.net/waltonwang/article/details/54098592 -------------------------------------------------------------------------------- /docker/第6章-Docker网络/images/bridge_network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第6章-Docker网络/images/bridge_network.png -------------------------------------------------------------------------------- /docker/第6章-Docker网络/images/network_access.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第6章-Docker网络/images/network_access.png -------------------------------------------------------------------------------- /docker/第6章-Docker网络/images/working.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第6章-Docker网络/images/working.png -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/26-Docker Compose简介.md: -------------------------------------------------------------------------------- 1 | # Docker Compose简介 2 | 3 | 经过前文讲解,我们可使用Dockerfile(或Maven)构建镜像,然后使用docker命令操作容器,例如docker run、docker kill等。 4 | 5 | 然而,使用分布式应用一般包含若干个服务,每个服务一般都会部署多个实例。如果每个服务都要手动启停,那么效率之低、维护量之大可想而知。 6 | 7 | 本章我们来讨论如何使用Docker Compose来轻松、高效地管理容器。为了简单起见,本章将Docker Compose简称为Compose。 8 | 9 | Compose是一个用于定义和运行多容器Docker应用程序的工具,前身是Fig。它非常适合用在开发、测试、构建CI工作流等场景。本书所使用的Compose版本是1.10.0。 10 | 11 | 12 | 13 | 14 | 15 | ## TIPS 16 | 17 | Compose的GitHub:[https://github.com/docker/compose](https://github.com/docker/compose) 18 | 19 | -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/27-安装Docker Compose.md: -------------------------------------------------------------------------------- 1 | # 安装Docker Compose 2 | 3 | 本节我们来讨论如何安装Compose。 4 | 5 | 6 | 7 | 8 | 9 | ## 安装Compose 10 | 11 | Compose有多种安装方式,例如通过Shell、pip以及将Compose作为容器安装等。本书讲解通过Shell来安装的方式,其他安装方式可详见官方文档:[https://docs.docker.com/compose/install/](https://docs.docker.com/compose/install/) 12 | 13 | (1) 通过以下命令自动下载并安装适应系统版本的Compose 14 | 15 | ```shell 16 | sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose 17 | ``` 18 | 19 | (2) 为安装脚本添加执行权限 20 | 21 | ```shell 22 | chmod +x /usr/local/bin/docker-compose 23 | ``` 24 | 25 | 这样,Compose就安装完成了。 26 | 27 | 可使用以下命令测试安装结果。 28 | 29 | ```shell 30 | docker-compose --version 31 | ``` 32 | 33 | 可输出类似于如下的内容。 34 | 35 | ```shell 36 | docker-compose version 1.16.1, build 1719ceb 37 | ``` 38 | 39 | 说明Compose已成功安装。 40 | 41 | 42 | 43 | 44 | 45 | ## 安装Compose命令补全工具 46 | 47 | 我们已成功安装Compose,然而,当我们输入`docker-compose` 并按下Tab键时,Compose并没有为我们补全命令。要想使用Compose的命令补全,我们需要安装命令补全工具。 48 | 49 | 命令补全工具在Bash和Zsh下的安装方式不同,本书演示的是Bash下的安装。其他Shell以及其他操作系统上的安装,可详见Docker的官方文档:[https://docs.docker.com/compose/completion/](https://docs.docker.com/compose/completion/) ,笔者不作赘述。 50 | 51 | * 执行以下命令,即可安装命令补全工具。 52 | 53 | ```shell 54 | curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose 55 | ``` 56 | 57 | 这样,在重新登录后,输入`docker-compose` 并按下Tab键,Compose就可自动补全命令了。 58 | 59 | 60 | 61 | ## 官方文档 62 | 63 | Docker Compose安装: 64 | 65 | 命令补全工具安装: -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/28-Docker Compose快速入门.md: -------------------------------------------------------------------------------- 1 | # Docker Compose快速入门 2 | 3 | 本节我们来探讨Compose使用的基本步骤,并编写一个简单示例快速入门。 4 | 5 | 6 | 7 | # 基本步骤 8 | 9 | 使用Compose大致有三个步骤: 10 | 11 | * 使用Dockerfile(或其他方式)定义应用程序环境,以便在任何地方重现该环境。 12 | * 在docker-compose.yml文件中定义组成应用程序的服务,以便各个服务在一个隔离的环境中一起运行。 13 | * 运行docker-compose up命令,启动并运行整个应用程序。 14 | 15 | 16 | 17 | 18 | 19 | # 入门示例 20 | 21 | 下面笔者以之前课上用到的Eureka为例讲解Compose的基本步骤。 22 | 23 | * 在`microservice-discovery-eureka-0.0.1-SNAPSHOT.jar` 所在路径(默认是项目的target目录)创建Dockerfile文件,并在其中添加如下内容。 24 | 25 | ```dockerfile 26 | FROM java:8 27 | VOLUME /tmp 28 | ADD microservice-discovery-eureka-0.0.1-SNAPSHOT.jar app.jar 29 | RUN bash -c 'touch /app.jar' 30 | EXPOSE 9000 31 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] 32 | ``` 33 | 34 | * 在`microservice-discovery-eureka-0.0.1-SNAPSHOT.jar` 所在路径创建文件docker-compose.yml,在其中添加如下内容。 35 | 36 | ```yaml 37 | version: '2' # 表示该docker-compose.yml文件使用的是Version 2 file format 38 | services: 39 | eureka: # 指定服务名称 40 | build: . # 指定Dockerfile所在路径 41 | ports: 42 | - "8761:8761" # 指定端口映射,类似docker run的-p选项,注意使用字符串形式 43 | ``` 44 | 45 | * 在`docker-compose.yml` 所在路径执行以下命令。 46 | 47 | ```shell 48 | docker-compose up 49 | ``` 50 | 51 | Compose就会自动构建镜像并使用镜像启动容器。我们也可使用`docker-compose up -d` 后台启动并运行这些容器。 52 | 53 | * 访问:`http://宿主机IP:8761/` ,即可访问Eureka Server首页。 54 | 55 | 56 | 57 | 58 | 59 | # 工程、服务、容器 60 | 61 | Docker Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker Compose运行目录下的所有文件(docker-compose.yml, extends文件或环境变量文件等)组成一个工程(默认为docker-compose.yml所在目录的目录名称)。一个工程可包含多个服务;每个服务中定义了容器运行的镜像、参数和依赖,一个服务可包括多个容器实例。 62 | 63 | 对应《入门示例》一节,工程名称是docker-compose.yml所在的目录名。该工程包含了1个服务,服务名称是eureka;执行docker-compose up时,启动了eureka服务的1个容器实例。 64 | 65 | -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/29-docker-compose.yml常用命令.md: -------------------------------------------------------------------------------- 1 | # docker-compose.yml常用命令 2 | 3 | docker-compose.yml是Compose的默认模板文件。该文件有多种写法,例如Version 1 file format、Version 2 file format、Version 2.1 file format、Version 3 file format等。其中,Version 1 file format将逐步被被弃用;Version 2.x及Version 3.x基本兼容,是未来的趋势。考虑到目前业界的使用情况,本节只讨论Version 2 file format下的常用命令。 4 | 5 | 6 | 7 | 8 | 9 | ## (1) build 10 | 11 | 配置构建时的选项,Compose会利用它自动构建镜像。build的值可以是一个路径,例如: 12 | 13 | ```yaml 14 | build: ./dir 15 | ``` 16 | 17 | 也可以是一个对象,用于指定Dockerfile和参数,例如: 18 | 19 | ```yaml 20 | build: 21 | context: ./dir 22 | dockerfile: Dockerfile-alternate 23 | args: 24 | buildno: 1 25 | ``` 26 | 27 | 28 | 29 | 30 | 31 | ## (2) command 32 | 33 | 覆盖容器启动后默认执行的命令。示例: 34 | 35 | ```yaml 36 | command: bundle exec thin -p 3000 37 | ``` 38 | 39 | 也可以是一个list,类似于Dockerfile中的CMD指令,格式如下: 40 | 41 | ```yaml 42 | command: [bundle, exec, thin, -p, 3000] 43 | ``` 44 | 45 | 46 | 47 | 48 | 49 | ## (3) dns 50 | 51 | 配置dns服务器。可以是一个值,也可以是一个列表。示例: 52 | 53 | ```yaml 54 | dns: 8.8.8.8 55 | dns: 56 | - 8.8.8.8 57 | - 9.9.9.9 58 | ``` 59 | 60 | 61 | 62 | 63 | 64 | ## (4) dns_search 65 | 66 | 配置DNS的搜索域名,可以是一个值,也可以是一个列表。示例: 67 | 68 | ```yaml 69 | dns_search: example.com 70 | dns_search: 71 | - dc1.example.com 72 | - dc2.example.com 73 | ``` 74 | 75 | 76 | 77 | 78 | 79 | ## (5) environment 80 | 81 | 环境变量设置,可使用数组或字典两种方式。示例: 82 | 83 | ```yaml 84 | environment: 85 | RACK_ENV: development 86 | SHOW: 'true' 87 | SESSION_SECRET: 88 | 89 | environment: 90 | - RACK_ENV=development 91 | - SHOW=true 92 | - SESSION_SECRET 93 | ``` 94 | 95 | 96 | 97 | 98 | 99 | ## (6) env_file 100 | 101 | 从文件中获取环境变量,可指定一个文件路径或路径列表。如果通过 `docker-compose -f FILE` 指定了Compose文件,那么env_file中的路径是Compose文件所在目录的相对路径。使用environment指定的环境变量会覆盖env_file指定的环境变量。示例: 102 | 103 | ```yaml 104 | env_file: .env 105 | 106 | env_file: 107 | - ./common.env # 共用 108 | - ./apps/web.env # web用 109 | - /opt/secrets.env # 密码用 110 | ``` 111 | 112 | 113 | 114 | 115 | 116 | ## (7) expose 117 | 118 | 暴露端口,只将端口暴露给连接的服务,而不暴露给宿主机。示例: 119 | 120 | ```yaml 121 | expose: 122 | - "3000" 123 | - "8000" 124 | ``` 125 | 126 | 127 | 128 | 129 | 130 | ## (8) external_links 131 | 132 | 连接到docker-compose.yml外部的容器,甚至并非Compose管理的容器,特别是提供共享或公共服务的容器。格式跟links类似,例如: 133 | 134 | ```yaml 135 | external_links: 136 | - redis_1 137 | - project_db_1:mysql 138 | - project_db_1:postgresql 139 | ``` 140 | 141 | 142 | 143 | 144 | 145 | ## (9) image 146 | 147 | 指定镜像名称或镜像id,如果本地不存在该镜像,Compose会尝试下载该镜像。 148 | 149 | 示例: 150 | 151 | ```yaml 152 | image: java 153 | ``` 154 | 155 | 156 | 157 | 158 | 159 | ## (10) links 160 | 161 | 连接到其他服务的容器。可以指定服务名称和服务别名( `SERVICE:ALIAS` ),也可只指定服务名称。例如: 162 | 163 | ```yaml 164 | web: 165 | links: 166 | - db 167 | - db:database 168 | - redis 169 | ``` 170 | 171 | 172 | 173 | 174 | 175 | ## (11) networks 176 | 177 | 详见本书《Docker Compose网络设置》一节。 178 | 179 | 180 | 181 | 182 | 183 | ## (12) network_mode 184 | 185 | 设置网络模式。示例: 186 | 187 | ```yaml 188 | network_mode: "bridge" 189 | network_mode: "host" 190 | network_mode: "none" 191 | network_mode: "service:[service name]" 192 | network_mode: "container:[container name/id]" 193 | ``` 194 | 195 | 196 | 197 | 198 | 199 | ## (13) ports 200 | 201 | 暴露端口信息,可使用`HOST:CONTAINER` 的格式,也可只指定容器端口(此时宿主机将会随机选择端口),类似于`docker run -p ` 。 202 | 203 | 需要注意的是,当使用`HOST:CONTAINER` 格式映射端口时,容器端口小于60将会得到错误的接口,因为yaml会把`xx:yy` 的数字解析为60进制。因此,建议使用字符串的形式。示例: 204 | 205 | ```yaml 206 | ports: 207 | - "3000" 208 | - "3000-3005" 209 | - "8000:8000" 210 | - "9090-9091:8080-8081" 211 | - "49100:22" 212 | - "127.0.0.1:8001:8001" 213 | - "127.0.0.1:5000-5010:5000-5010" 214 | ``` 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | ## (14) volumes 223 | 224 | 卷挂载路径设置。可以设置宿主机路径 (`HOST:CONTAINER`) ,也可指定访问模式 (`HOST:CONTAINER:ro`)。示例: 225 | 226 | ```yaml 227 | volumes: 228 | # Just specify a path and let the Engine create a volume 229 | - /var/lib/mysql 230 | 231 | # Specify an absolute path mapping 232 | - /opt/data:/var/lib/mysql 233 | 234 | # Path on the host, relative to the Compose file 235 | - ./cache:/tmp/cache 236 | 237 | # User-relative path 238 | - ~/configs:/etc/configs/:ro 239 | 240 | # Named volume 241 | - datavolume:/var/lib/mysql 242 | ``` 243 | 244 | 245 | 246 | 247 | 248 | ## (15) volumes_from 249 | 250 | 从另一个服务或容器挂载卷。可指定只读(ro)或读写(rw),默认是读写(rw)。示例: 251 | 252 | ```yaml 253 | volumes_from: 254 | - service_name 255 | - service_name:ro 256 | - container:container_name 257 | - container:container_name:rw 258 | ``` 259 | 260 | 261 | 262 | 263 | 264 | ## TIPS 265 | 266 | (1) docker-compose.yml还有很多其他命令,比如depends_on、pid、devices等。限于篇幅,笔者仅挑选常用的命令进行讲解,其他命令不作赘述。感兴趣的读者们可参考官方文档:[https://docs.docker.com/compose/compose-file/](https://docs.docker.com/compose/compose-file/) 。 267 | 268 | 269 | -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/30-docker-compose常用命令.md: -------------------------------------------------------------------------------- 1 | # docker-compose常用命令 2 | 3 | 和docker命令一样,docker-compose命令也有很多选项。下面我们来详细探讨docker-compose的常用命令。 4 | 5 | 6 | 7 | 8 | 9 | ## build 10 | 11 | 构建或重新构建服务。服务被构建后将会以`project_service` 的形式标记,例如:`composetest_db` 。 12 | 13 | 14 | 15 | 16 | 17 | ## help 18 | 19 | 查看指定命令的帮助文档,该命令非常实用。docker-compose所有命令的帮助文档都可通过该命令查看。 20 | 21 | ```shell 22 | docker-compose help COMMAND 23 | ``` 24 | 25 | 示例: 26 | 27 | ```shell 28 | docker-compose help build # 查看docker-compose build的帮助 29 | ``` 30 | 31 | 32 | 33 | 34 | 35 | ## kill 36 | 37 | 通过发送`SIGKILL` 信号停止指定服务的容器。示例: 38 | 39 | ``` 40 | docker-compose kill eureka 41 | ``` 42 | 43 | 该命令也支持通过参数来指定发送的信号,例如: 44 | 45 | ```shell 46 | docker-compose kill -s SIGINT 47 | ``` 48 | 49 | 50 | 51 | 52 | 53 | ## logs 54 | 55 | 查看服务的日志输出。 56 | 57 | 58 | 59 | 60 | 61 | ## port 62 | 63 | 打印绑定的公共端口。示例: 64 | 65 | ```shell 66 | docker-compose port eureka 8761 67 | ``` 68 | 69 | 这样就可输出eureka服务8761端口所绑定的公共端口。 70 | 71 | 72 | 73 | 74 | 75 | ## ps 76 | 77 | 列出所有容器。示例: 78 | 79 | ```shell 80 | docker-compose ps 81 | ``` 82 | 83 | 也可列出指定服务的容器,示例: 84 | 85 | ```shell 86 | docker-compose ps eureka 87 | ``` 88 | 89 | 90 | 91 | 92 | 93 | 94 | ## pull 95 | 96 | 下载服务镜像。 97 | 98 | 99 | 100 | 101 | 102 | ## rm 103 | 104 | 删除指定服务的容器。示例: 105 | 106 | ```shell 107 | docker-compose rm eureka 108 | ``` 109 | 110 | 111 | 112 | 113 | 114 | ## run 115 | 116 | 在一个服务上执行一个命令。示例: 117 | 118 | ```shell 119 | docker-compose run web bash 120 | ``` 121 | 122 | 这样即可启动一个web服务,同时执行bash命令。 123 | 124 | 125 | 126 | 127 | 128 | ## scale 129 | 130 | 设置指定服务运行容器的个数,以service=num的形式指定。示例: 131 | 132 | ```shell 133 | docker-compose scale user=3 movie=3 134 | ``` 135 | 136 | 137 | 138 | 139 | 140 | ## start 141 | 142 | 启动指定服务已存在的容器。示例: 143 | 144 | ```shell 145 | docker-compose start eureka 146 | ``` 147 | 148 | 149 | 150 | 151 | 152 | ## stop 153 | 154 | 停止已运行的容器。示例: 155 | 156 | ```shell 157 | docker-compose stop eureka 158 | ``` 159 | 160 | 停止后,可使用`docker-compose start` 再次启动这些容器。 161 | 162 | 163 | 164 | 165 | 166 | ## up 167 | 168 | 构建、创建、重新创建、启动,连接服务的相关容器。所有连接的服务都会启动,除非它们已经运行。 169 | 170 | `docker-compose up` 命令会聚合所有容器的输出,当命令退出时,所有容器都会停止。 171 | 172 | 使用`docker-compose up -d` 可在后台启动并运行所有容器。 173 | 174 | 175 | 176 | 177 | 178 | ## TIPS 179 | 180 | (1) 本节仅讨论常用的docker-compose命令,其他命令可详见Docker官方文档:[https://docs.docker.com/compose/reference/overview/](https://docs.docker.com/compose/reference/overview/) 。 -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/31-Docker Compose网络设置.md: -------------------------------------------------------------------------------- 1 | # Docker Compose网络设置 2 | 3 | 本节我们来详细探讨Compose的网络设置。本节介绍的网络特性仅适用于Version 2 file format,Version 1 file format不支持该特性。 4 | 5 | 6 | 7 | # 基本概念 8 | 9 | 默认情况下,Compose会为我们的应用创建一个网络,服务的每个容器都会加入该网络中。这样,容器就可被该网络中的其他容器访问,不仅如此,该容器还能以服务名称作为hostname被其他容器访问。 10 | 11 | 默认情况下,应用程序的网络名称基于Compose的工程名称,而项目名称基于docker-compose.yml所在目录的名称。如需修改工程名称,可使用--project-name标识或COMPOSE_PORJECT_NAME环境变量。 12 | 13 | 举个例子,假如一个应用程序在名为myapp的目录中,并且docker-compose.yml如下所示: 14 | 15 | ```yaml 16 | version: '2' 17 | services: 18 | web: 19 | build: . 20 | ports: 21 | - "8000:8000" 22 | db: 23 | image: postgres 24 | ``` 25 | 26 | 当我们运行docker-compose up时,将会执行以下几步: 27 | 28 | * 创建一个名为myapp_default的网络; 29 | * 使用web服务的配置创建容器,它以“web”这个名称加入网络myapp_default; 30 | * 使用db服务的配置创建容器,它以“db”这个名称加入网络myapp_default。 31 | 32 | 容器间可使用服务名称(web或db)作为hostname相互访问。例如,web这个服务可使用`postgres://db:5432` 访问db容器。 33 | 34 | 35 | 36 | 37 | 38 | # 更新容器 39 | 40 | 当服务的配置发生更改时,可使用docker-compose up命令更新配置。 41 | 42 | 此时,Compose会删除旧容器并创建新容器。新容器会以不同的IP地址加入网络,名称保持不变。任何指向旧容器的连接都会被关闭,容器会重新找到新容器并连接上去。 43 | 44 | 45 | 46 | # links 47 | 48 | 前文讲过,默认情况下,服务之间可使用服务名称相互访问。links允许我们定义一个别名,从而使用该别名访问其他服务。举个例子: 49 | 50 | ```yaml 51 | version: '2' 52 | services: 53 | web: 54 | build: . 55 | links: 56 | - "db:database" 57 | db: 58 | image: postgres 59 | ``` 60 | 61 | 这样web服务就可使用db或database作为hostname访问db服务了。 62 | 63 | 64 | 65 | 66 | 67 | # 指定自定义网络 68 | 69 | 一些场景下,默认的网络配置满足不了我们的需求,此时我们可使用networks命令自定义网络。networks命令允许我们创建更加复杂的网络拓扑并指定自定义网络驱动和选项。不仅如此,我们还可使用networks将服务连接到不是由Compose管理的、外部创建的网络。 70 | 71 | 如下,我们在其中定义了两个自定义网络。 72 | 73 | ```yaml 74 | version: '2' 75 | 76 | services: 77 | proxy: 78 | build: ./proxy 79 | networks: 80 | - front 81 | app: 82 | build: ./app 83 | networks: 84 | - front 85 | - back 86 | db: 87 | image: postgres 88 | networks: 89 | - back 90 | 91 | networks: 92 | front: 93 | # Use a custom driver 94 | driver: custom-driver-1 95 | back: 96 | # Use a custom driver which takes special options 97 | driver: custom-driver-2 98 | driver_opts: 99 | foo: "1" 100 | bar: "2" 101 | ``` 102 | 103 | 其中,proxy服务与db服务隔离,两者分别使用自己的网络;app服务可与两者通信。 104 | 105 | 由本例不难发现,使用networks命令,即可方便实现服务间的网络隔离与连接。 106 | 107 | 108 | 109 | 110 | 111 | # 配置默认网络 112 | 113 | 除自定义网络外,我们也可为默认网络自定义配置。 114 | 115 | ```yaml 116 | version: '2' 117 | 118 | services: 119 | web: 120 | build: . 121 | ports: 122 | - "8000:8000" 123 | db: 124 | image: postgres 125 | 126 | networks: 127 | default: 128 | # Use a custom driver 129 | driver: custom-driver-1 130 | ``` 131 | 132 | 这样,就可为该应用指定自定义的网络驱动。 133 | 134 | 135 | 136 | 137 | 138 | # 使用已存在的网络 139 | 140 | 一些场景下,我们并不需要创建新的网络,而只需加入已存在的网络,此时可使用external选项。示例: 141 | 142 | ```yaml 143 | networks: 144 | default: 145 | external: 146 | name: my-pre-existing-network 147 | ``` -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/32-小练习:使用Docker Compose编排WordPress博客.md: -------------------------------------------------------------------------------- 1 | # 小练习:使用Docker Compose编排WordPress博客 2 | 3 | ```yaml 4 | version: '2' 5 | services: 6 | mysql: 7 | image: mysql:5.7 8 | expose: 9 | - "3306" 10 | environment: 11 | - MYSQL_ROOT_PASSWORD=123456 12 | wordpress: 13 | image: wordpress 14 | ports: 15 | - "80:80" 16 | environment: 17 | - WORDPRESS_DB_HOST=mysql 18 | - WORDPRESS_DB_USER=root 19 | - WORDPRESS_DB_PASSWORD=123456 20 | ``` 21 | 22 | 23 | 24 | **WARNING** 25 | 26 | 这里,MySQL镜像只能用5.x的镜像,不能使用8.x的镜像。否则WordPress无法正常连接到MySQL。原因是:目前PHP 7.x(例如7.1.4)所使用的字符集与MySQL 8.x所使用的默认字符集不同: -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/33-控制服务启动顺序.md: -------------------------------------------------------------------------------- 1 | # 控制服务启动顺序 2 | 3 | 在生产中,往往有严格控制服务启动顺序的需求。然而Docker Compose自身并不具备该能力。要想实现启动顺序的控制,Docker Compose建议我们使用: 4 | 5 | * [wait-for-it](https://github.com/vishnubob/wait-for-it) 6 | * [dockerize](https://github.com/jwilder/dockerize) 7 | * [wait-for](https://github.com/Eficode/wait-for) 8 | 9 | 本文演示如何使用wait-for-it 来控制服务的启动顺序。 10 | 11 | 还用前面编排WordPress博客的例子,现在我们想让MySQL先启动,启动完成后再启动WordPress。 12 | 13 | 14 | 15 | 16 | 17 | ## 分析 18 | 19 | 分析:找到WordPress的Dockerfile: 20 | 21 | 可看到类似如下的内容: 22 | 23 | ```dockerfile 24 | COPY docker-entrypoint.sh /usr/local/bin/ 25 | ENTRYPOINT ["docker-entrypoint.sh"] 26 | CMD ["apache2-foreground"] 27 | ``` 28 | 29 | 也就是说,这个WordPress的Dockerfile执行了命令:`docker-entrypoint.sh apache2-foreground` 。 30 | 31 | > 顺便再复习一下,ENTRYPOINT与CMD的区别——ENTRYPOINT指令是不会被覆盖的,CMD指令会覆盖。详见博客: 。 32 | 33 | 34 | 35 | 36 | 37 | ## wait-for-it 38 | 39 | 在wait-for-it的官方GiTHub中,有详细的例子: 40 | 41 | 要想使用wait-for-it,只需使用如下形式即可: 42 | 43 | ``` 44 | wait-for-it.sh 想等的地址:端口 -- 原本想执行的命令 45 | ``` 46 | 47 | 48 | 49 | 50 | 51 | ## 答案 52 | 53 | 分析到这里,答案就很简单了:只需在WordPress的容器中添加wait-for-it.sh,然后将原本的命令用wait-for-it包裹,即可实现控制启动顺序的目标。 54 | 55 | ```yaml 56 | version: '2' 57 | services: 58 | mysql: 59 | image: mysql:5.7 60 | expose: 61 | - "3306" 62 | environment: 63 | - MYSQL_ROOT_PASSWORD=123456 64 | wordpress: 65 | image: wordpress 66 | ports: 67 | - "80:80" 68 | volumes: 69 | - ./wait-for-it.sh:/wait-for-it.sh 70 | environment: 71 | - WORDPRESS_DB_HOST=mysql 72 | - WORDPRESS_DB_USER=root 73 | - WORDPRESS_DB_PASSWORD=123456 74 | entrypoint: "sh /wait-for-it.sh mysql:3306 -- docker-entrypoint.sh" 75 | command: ["apache2-foreground"] 76 | ``` 77 | 78 | 79 | 80 | 81 | 82 | ## 参考文档 83 | 84 | * 《Controlling startup order in Compose》: 。 -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/34-在生产环境中使用Docker Compose.md: -------------------------------------------------------------------------------- 1 | # 在生产环境中使用Docker Compose 2 | 3 | 在development中使用Compose定义应用程序时,可使用此定义,在不同环境(如CI,staging和production)中运行应用程序。 4 | 5 | 部署应用最简单的方法是在单机服务器上运行,类似于运行development环境的方式。如果要对应用程序扩容,可在Swarm集群上运行Compose应用程序。 6 | 7 | 8 | 9 | 10 | 11 | ### Modify your Compose file for production(为生产环境修改您的Compose文件) 12 | 13 | 您几乎肯定会对您的应用配置进行更改,从而使这些配置更适合线上环境。 这些更改可能包括: 14 | 15 | * 删除任何绑定到应用程序代码的Volume,以便代码保持在容器内,不能从外部更改 16 | * 绑定到主机上的不同端口 17 | * 设置不同的环境变量(例如,减少日志的冗长程度或启用email发送) 18 | * DEBUG INFO WARN ERROR FETAL 19 | * 指定重启策略(例如, `restart: always` ),从而避免停机 20 | * 添加额外服务(例如,日志聚合器) 21 | 22 | 因此,您可能需要定义一个额外的Compose文件,比如`production.yml` ,它指定了适用于生产的配置。此配置文件只需包含从原始Compose文件的修改。该附加Compose文件,可在原始的`docker-compose.yml` 基础上被应用,从而创建新的配置。 23 | 24 | 一旦获得了第二个配置文件,可使用`-f` 选项告诉Compose: 25 | 26 | ``` 27 | docker-compose -f docker-compose.yml -f production.yml up -d 28 | ``` 29 | 30 | 请参阅 [Using multiple compose files](https://docs.docker.com/compose/extends/#different-environments) 获取更完整的示例。 31 | 32 | 33 | 34 | 35 | 36 | ### Deploying changes(部署修改) 37 | 38 | 当您更改应用代码时,您需要重新构建镜像并重新创建容器。例如,重新部署名为`web` 的服务,可使用: 39 | 40 | ``` 41 | $ docker-compose build web 42 | $ docker-compose up --no-deps -d web 43 | ``` 44 | 45 | 这将会先重新构建`web` 的镜像,然后停止、销毁、重新创建`web` 服务。 `--no-deps` 标志可防止Compose重新创建任何`web` 依赖的服务。 46 | 47 | 48 | 49 | 50 | 51 | ### Running Compose on a single server(单机服务器上运行Compose) 52 | 53 | 通过适当地设置`DOCKER_HOST` 、`DOCKER_TLS_VERIFY` 和`DOCKER_CERT_PATH` 等环境变量,可使用Compose将应用程序部署到远程的Docker主机。 对于像这样的任务,[Docker Machine](https://docs.docker.com/machine/overview/) 可使本地/远程Docker主机管理变得非常简单,即使您没有远程部署也推荐使用Docker Machine。 54 | 55 | 一旦您设置了如上环境变量,所有正常的`docker-compose` 命令将无需进一步的配置。 56 | 57 | 58 | 59 | 60 | 61 | ### Running Compose on a Swarm cluster(在Swarm集群上运行Compose) 62 | 63 | [Docker Swarm](https://docs.docker.com/swarm/overview/) ,是一款Docker原生的集群系统,它暴露了与单个Docker主机相同的API,这意味着您可在Swarm实例上使用Compose,并在多个主机上运行应用程序。 64 | 65 | 阅读更多关于集成指Compose/Swarm整合的内容,请详见 [integration guide](https://docs.docker.com/compose/swarm/) 。 66 | 67 | 68 | 69 | 70 | 71 | ## 原文 72 | 73 | -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/35-实战:使用Docker Compose运行ELK.md: -------------------------------------------------------------------------------- 1 | # 实战:使用Docker Compose运行ELK 2 | 3 | * ElasticSearch【存储】 4 | * Logtash【日志聚合器】 5 | * Kibana【界面】 6 | 7 | 答案: 8 | 9 | ```yaml 10 | version: '2' 11 | services: 12 | elasticsearch: 13 | image: elasticsearch 14 | # command: elasticsearch 15 | ports: 16 | - "9200:9200" # REST API端口 17 | - "9300:9300" # RPC端口 18 | logstash: 19 | image: logstash 20 | command: logstash -f /etc/logstash/conf.d/logstash.conf 21 | volumes: 22 | - ./config:/etc/logstash/conf.d 23 | - /opt/build:/opt/build 24 | ports: 25 | - "5000:5000" 26 | kibana: 27 | image: kibana 28 | environment: 29 | - ELASTICSEARCH_URL=http://elasticsearch:9200 30 | ports: 31 | - "5601:5601" 32 | ``` 33 | 34 | `logstash.conf` 参考示例: 35 | 36 | ```json 37 | input { 38 | file { 39 | codec => json 40 | path => "/opt/build/*.json" 41 | } 42 | } 43 | filter { 44 | grok { 45 | match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}\s+%{LOGLEVEL:severity}\s+\[%{DATA:service},%{DATA:trace},%{DATA:span},%{DATA:exportable}\]\s+%{DATA:pid}---\s+\[%{DATA:thread}\]\s+%{DATA:class}\s+:\s+%{GREEDYDATA:rest}" } 46 | } 47 | } 48 | output { 49 | elasticsearch { 50 | hosts => "elasticsearch:9200" 51 | } 52 | } 53 | ``` 54 | 55 | 56 | 57 | 58 | 59 | ## 参考文档 60 | 61 | -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/36-使用Docker Compose伸缩应用.md: -------------------------------------------------------------------------------- 1 | # 使用Docker Compose伸缩应用 2 | 3 | 执行: 4 | 5 | `docker-compose scale 服务名称=服务实例个数` 即可。 6 | 7 | -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/images/14-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第7章-Docker Compose/images/14-1.png -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/images/14-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第7章-Docker Compose/images/14-2.png -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/images/14-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第7章-Docker Compose/images/14-3.png -------------------------------------------------------------------------------- /docker/第7章-Docker Compose/wait-for-it-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/docker/第7章-Docker Compose/wait-for-it-master.zip -------------------------------------------------------------------------------- /kubernetes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/.DS_Store -------------------------------------------------------------------------------- /kubernetes/01-Overview/K8s组件.md: -------------------------------------------------------------------------------- 1 | # K8s组件 2 | 3 | 本文概述了Kubernetes集群中所需的各种组件。 4 | 5 | 6 | 7 | ## Master组件 8 | 9 | Master组件提供K8s集群的控制面板。Master对集群进行全局决策(例如调度),以及检测和响应集群事件(例如:当replication controller所设置的`replicas` 不够时,启动一个新的Pod)。 10 | 11 | Master可在集群中的任意节点上运行。然而,简单起见,设置脚本通常在同一个VM上启动所有Master组件,并且不会在该VM上运行用户的容器。请阅读 [Building High-Availability Clusters](https://kubernetes.io/docs/admin/high-availability/) 以实现多主机VM配置。 12 | 13 | 14 | 15 | ### kube-apiserver 16 | 17 | [kube-apiserver](https://kubernetes.io/docs/admin/kube-apiserver/) 暴露Kubernetes的API。它是Kubernetes控制能力的前端。它被设计为可水平扩展——也就是通过部署更多实例来实现扩容。详见 [Building High-Availability Clusters](https://kubernetes.io/docs/admin/high-availability/) 。 18 | 19 | 20 | 21 | ### etcd 22 | 23 | [etcd](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/) 用作Kubernetes的后端存储。集群的所有数据都存储在此。请为你Kubernetes集群的etcd数据提供备份计划。 24 | 25 | 26 | 27 | ### kube-controller-manager 28 | 29 | [kube-controller-manager](https://kubernetes.io/docs/admin/kube-controller-manager/) 运行Controller,它们是处理集群中常规任务的后台线程。逻辑上来讲,每个Controller都是一个单独的进程,但为了降低复杂性,它们都被编译成独立的二进制文件并运行在一个进程中。 30 | 31 | 这些控制器包括: 32 | 33 | - Node Controller:当节点挂掉时,负责响应。 34 | - Replication Controller:负责维护系统中每个replication controller对象具有正确数量的Pod。 35 | - Endpoints Controller:填充Endpoint对象(即:连接Service&Pod)。 36 | - Service Account & Token Controllers:为新的namespace创建默认帐户和API access tokens。 37 | 38 | 39 | 40 | 41 | ### cloud-controller-manager 42 | 43 | cloud-controller-manager运行着与底层云提供商交互的Controller。cloud-controller-manager是在Kubernetes 1.6版中引入的,处于Alpha阶段。 44 | 45 | cloud-controller-manager仅运行云提供商特定的Controller循环。您必须在kube-controller-manager中禁用这些Controller循环。可在启动kube-controller-manager时将`--cloud-provider` 标志设为 `external` 来禁用控制器循环。 46 | 47 | cloud-controller-manager允许云供应商代码和Kubernetes内核独立发展。在以前的版本中,核心的Kubernetes代码依赖于特定云提供商的功能代码。在未来的版本中,云供应商的特定代码应由云供应商自己维护,并在运行Kubernetes时与cloud-controller-manager相关联。 48 | 49 | 以下控制器存在云提供商依赖: 50 | 51 | - Node Controller:用于检查云提供商,从而确定Node在停止响应后从云中删除 52 | - Route Controller:用于在底层云基础设施中设置路由 53 | - Service Controller:用于创建、更新以及删除云提供商负载均衡器 54 | - Volume Controller:用于创建、连接和装载Volume,并与云提供商进行交互,从而协调Volume 55 | 56 | 57 | 58 | 59 | ### kube-scheduler 60 | 61 | [kube-scheduler](https://kubernetes.io/docs/admin/kube-scheduler/) 监视新创建的、还没分配Node的Pod,并选择一个Node供这些Pod运行。 62 | 63 | 64 | 65 | ### addons(插件) 66 | 67 | Addon是实现集群功能的Pod和Service。Pod可由Deployment、ReplicationController等进行管理。Namespace的插件对象则是在`kube-system` 这个namespace中被创建的。 68 | 69 | Addon manager创建并维护addon的资源。详见这里: [here](http://releases.k8s.io/HEAD/cluster/addons) 。 70 | 71 | 72 | 73 | #### DNS 74 | 75 | 虽然其他Addon不是严格要求的,但所有Kubernetes集群都应该有 [cluster DNS](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) ,许多用例都依赖于它。 76 | 77 | Cluster DNS是一个DNS服务器,它为Kubernetes服务提供DNS记录。 78 | 79 | Kubernetes启动的容器会自动将该DNS服务器包含在DNS搜索中。 80 | 81 | 82 | 83 | #### Web UI (Dashboard) 84 | 85 | [Dashboard](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/) 是一个Kubernetes集群通用、基于Web的UI。它允许用户管理/排错集群中应用程序以及集群本身。 86 | 87 | 88 | 89 | #### Container Resource Monitoring(容器资源监控) 90 | 91 | [Container Resource Monitoring](https://kubernetes.io/docs/tasks/debug-application-cluster/resource-usage-monitoring/) 将容器的通用时序指标记录到一个中心化的数据库中,并提供一个UI以便于浏览该数据。 92 | 93 | 94 | 95 | #### Cluster-level Logging(集群级别的日志) 96 | 97 | [Cluster-level logging](https://kubernetes.io/docs/concepts/cluster-administration/logging/) 机制负责将容器的日志存储到具有搜索/浏览界面的中央日志存储中去。 98 | 99 | 100 | 101 | 102 | 103 | ## Node组件 104 | 105 | Node组件在每个Node上运行,维护运行的Pod并提供Kubernetes运行时环境。 106 | 107 | 108 | 109 | ### kubelet 110 | 111 | 112 | [kubelet](https://kubernetes.io/docs/admin/kubelet/) 是主要的Node代理。它监视已分配到其Node上的Pod(通过apiserver或本地配置文件)和: 113 | 114 | - 装载Pod所需的Volume。 115 | - 下载Pod的secret。 116 | - 通过Docker(或实验时使用rkt)运行Pod的容器。 117 | - 定期执行任何被请求容器的活动探针(liveness probes)。 118 | - 在必要时创建*mirror pod* ,从而将pod的状态报告回系统的其余部分。 119 | - 将节点的状态报告回系统的其余部分。 120 | 121 | 122 | 123 | 124 | ### kube-proxy 125 | 126 | [kube-proxy](https://kubernetes.io/docs/admin/kube-proxy/) 在主机上维护网络规则并执行连接转发,从而来实现Kubernetes服务抽象。 127 | 128 | 129 | 130 | ### docker 131 | 132 | `docker` 用于运行容器。 133 | 134 | 135 | 136 | ### rkt 137 | 138 | `rkt` 是一个Docker的替代品,支持在实验中运行容器 139 | 140 | 141 | 142 | ### supervisord 143 | 144 | `supervisord` 是一个轻量级的进程监控/控制系统,可用于保持kubelet和docker运行。 145 | 146 | 147 | 148 | ### fluentd 149 | 150 | `fluentd` 是一个守护进程,利用它可实现 [cluster-level logging](https://kubernetes.io/docs/concepts/overview/components/#cluster-level-logging) 。 151 | 152 | -------------------------------------------------------------------------------- /kubernetes/01-Overview/Kubernetes API.md: -------------------------------------------------------------------------------- 1 | # Kubernetes API 2 | 3 | [API conventions doc](https://git.k8s.io/community/contributors/devel/api-conventions.md) 中描述了API的总体规范。 4 | 5 | [API Reference](https://kubernetes.io/docs/reference) 中描述了API端点、资源类型和样本。 6 | 7 | [access doc](https://kubernetes.io/docs/admin/accessing-the-api) 讨论了API的远程访问。 8 | 9 | Kubernetes API也是系统声明式配置模式的基础。 [Kubectl](https://kubernetes.io/docs/user-guide/kubectl) 命令行工具可用于创建、更新、删除以及获取API对象。 10 | 11 | Kubernetes也会存储其API资源方面的序列化状态(目前存在 [etcd](https://coreos.com/docs/distributed-configuration/getting-started-with-etcd/) 中)。 12 | 13 | Kubernetes本身被分解成了多个组件,通过其API进行交互。 14 | 15 | 16 | 17 | 18 | 19 | ## API更改 20 | 21 | 根据我们的经验,任何成功的系统都需要随着新用例的出现或现有的变化而发展和变化。因此,我们预计Kubernetes API将会不断变化和发展。但是,在很长一段时间内并不会破坏与现有客户端的兼容性。一般来说,新的API资源和新的资源字段通常可被频繁添加。消除资源或字段将需遵循 [API deprecation policy](https://kubernetes.io/docs/reference/deprecation-policy/) 。 22 | 23 | [API change document](https://git.k8s.io/community/contributors/devel/api_changes.md) 详细介绍了兼容更改以及如何更改API的内容。 24 | 25 | 26 | 27 | 28 | 29 | ## OpenAPI与Swagger定义 30 | 31 | 完整的API详情使用 [Swagger v1.2](http://swagger.io/) 和 [OpenAPI](https://www.openapis.org/) 记录。Kubernetes apiserver(又名“master”)公开了一个路径是`/swaggerapi` API,该API使用Swagger v1.2 Kubernetes API规范。 您也可以通过将`--enable-swagger-ui=true` 标志传递给apiserver,从而浏览`/swagger-ui` 的启用UI的API文档。 32 | 33 | 从Kubernetes 1.4开始,OpenAPI规范也可在 [`/swagger.json`](https://git.k8s.io/kubernetes/api/openapi-spec/swagger.json) 。当我们从Swagger v1.2转换到OpenAPI(又名Swagger v2.0)时,一些工具(例如:kubectl和swagger-ui)仍在使用v1.2规范。OpenAPI规范在Kubernetes 1.5中,进入Beta阶段。 34 | 35 | Kubernetes为主要用于集群内通信的API实现了另一种基于Protobuf的序列化格式,在 [design proposal](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/protobuf.md) 有记录,每个schema的IDL文件都存放在定义该API对象的Go语言包中。 36 | 37 | 38 | 39 | 40 | 41 | ## API版本 42 | 43 | 为了更容易地消除字段或重组资源表示,Kubernetes支持多种API版本,每种API版本都有不同的API路径,例如`/api/v1`或`/apis/extensions/v1beta1` 。 44 | 45 | 我们选择在API级别,而非资源级别/字段级别使用版本控制,从而确保API提供清晰、一致的系统资源和行为视图,以及控制对终极API/实验API的访问。JSON和Protobuf序列化schema遵循相同的schema更改准则——以下所有描述都涵盖了两种格式。 46 | 47 | 请注意,API版本控制和软件版本控制仅仅是间接相关的关系。 [API and release versioning proposa(API和版本发布提案)l](https://git.k8s.io/community/contributors/design-proposals/release/versioning.md) 描述了API版本控制和软件版本控制之间的关系。 48 | 49 | 不同的API版本意味着不同程度的稳定性和支持。[API Changes documentation](https://git.k8s.io/community/contributors/devel/api_changes.md#alpha-beta-and-stable-versions) 详细描述了每个级别的标准。概括如下: 50 | 51 | - Alpha级别: 52 | - 版本名称包含`alpha` (例如`v1alpha1` ) 53 | - 可能有一些bug,启用该功能可能会显示错误。 默认禁用 54 | - 一些功能可能随时会被废弃,恕不另行通知 55 | - API可能会以不兼容的方式更改,恕不另行通知 56 | - 建议仅在短期测试集群中使用,因为增加了bug带来的风险,而且缺乏长期支持 57 | - Beta级别: 58 | - 版本名称包含`beta` (例如`v2beta3` ) 59 | - 代码经过了良好的测试。启用该功能被认为是安全的。 默认启用 60 | - 整体功能不会被删除,尽管细节可能会改变 61 | - 对象的schema/语义可能会在后续的beta版/稳定版本中以不兼容的方式发生变化。发生这种情况时,我们将提供迁移到下一个版本的说明。 这可能需要删除、编辑和重新创建API对象。编辑进程可能需要一些思考。依赖该功能的应用程序可能需要停机。 62 | - 推荐仅用于非关键业务用途,因为后续版本中可能会发生不兼容的更改。如果您有多个可独立升级的集群,则可放宽此限制。 63 | - **请尝试我们的beta功能并给他们反馈!一旦他们退出beta状态,我们就不会做更多的改变。** 64 | 65 | 66 | - Stable等级: 67 | - 版本名称为`vX` ,其中`X`为整数。 68 | - 稳定版本的功能将会出现在许多后续版本中。 69 | 70 | 71 | 72 | 73 | 74 | ## API组 75 | 76 | 为了使Kubernetes API扩展更容易,我们实现了 [*API groups*](https://git.k8s.io/community/contributors/design-proposals/api-machinery/api-group.md) 。 API组可在序列化对象的`apiVersion` 字段中使用一个REST路径指定。 77 | 78 | 目前可使用的几个API组: 79 | 80 | 1. “core”(由于没有明确的组名称,通常称为“legacy”)组,它的REST路径是`/api/v1` 。例如`apiVersion: v1` 。 81 | 2. 命名组是REST路径`/apis/$GROUP_NAME/$VERSION` ,并使用`apiVersion: $GROUP_NAME/$VERSION` (例如`apiVersion: batch/v1` )。 支持的API组的完整列表可详见:[Kubernetes API reference](https://kubernetes.io/docs/reference/) 。 82 | 83 | 使用 [custom resources](https://kubernetes.io/docs/concepts/api-extension/custom-resources/) 扩展API有两个支持的路径: 84 | 85 | 1. [CustomResourceDefinition](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/) 适用于非常基本的CRUD需求的用户。 86 | 2. 即将推出:用户需要完整的Kubernetes API语法,这些语法可实现自己的apiserver,并使用 [aggregator](https://git.k8s.io/community/contributors/design-proposals/api-machinery/aggregated-api-servers.md) 无缝连接客户端。 87 | 88 | 89 | 90 | 91 | 92 | ## 启用API组 93 | 94 | 默认情况下,某些资源和API组已被启用。可通过在apiserver上设置`--runtime-config` 来启用或禁用它们。 `--runtime-config`接受逗号分隔的值。例如:要禁用`batch / v1` ,请设置`--runtime-config=batch/v1=false` ;想启用`batch/v2alpha1` ,可设置`--runtime-config=batch/v2alpha1` 。 该标志接受逗号分隔的一组键值对,键值对描述了apiserver的运行时配置。 95 | 96 | **重要信息**:启用或禁用组或资源,需要重启apiserver和controller-manager来获取`--runtime-config` 的更改。 97 | 98 | 99 | 100 | 101 | 102 | ## 启用组中的资源 103 | 104 | 默认情况下,DaemonSets、Deployments、HorizontalPodAutoscalers、Ingress、Jobs和ReplicaSets都被启用。可通过在apiserver上设置`--runtime-config` 来启用其他扩展资源。`--runtime-config` 接受逗号分隔值。 例如:要禁用Deployments和Ingress,可设置 105 | 106 | ``` 107 | --runtime-config=extensions/v1beta1/deployments=false,extensions/v1beta1/ingress=false 108 | ``` 109 | 110 | 111 | 112 | 113 | 114 | ## 原文 115 | 116 | -------------------------------------------------------------------------------- /kubernetes/01-Overview/Working with Kubernetes Objects/Annotation.md: -------------------------------------------------------------------------------- 1 | # Annotation(注解) 2 | 3 | 可使用Kubernetes annotation将任意的非识别元数据附加到对象。 客户端可取得此元数据。 4 | 5 | 6 | 7 | 8 | 9 | ## 将元数据附加到对象 10 | 11 | 您可以使用标签或Annotation将元数据附加到Kubernetes对象。标签可用于选择对象并查找满足某些条件的对象集合。相比之下,Annotation不用于标识和选择对象。Annotation中的元数据可大可小,结构化或非结构化,并且可包括标签所不允许的字符。 12 | 13 | Annotation类似于标签,是键值对映射: 14 | 15 | ```json 16 | "annotations": { 17 | "key1" : "value1", 18 | "key2" : "value2" 19 | } 20 | ``` 21 | 22 | 类似以下信息可记录到Annotation中: 23 | 24 | - 由declarative configuration layer管理的字段。将这些字段附加为Annotation,可将它们与客户端或服务器设置的默认值、自动生成的字段或以及auto-sizing或auto-scaling的系统所设置的字段区分开。 25 | - 构建信息、发布信息或镜像信息,如时间戳、release ID、git分支、PR编号、镜像哈希以及注册表地址。 26 | - 指向日志、监控、分析或审计仓库。 27 | 28 | 29 | - 用于调试的客户端库或工具的信息:例如名称、版本和构建信息。 30 | - 用户或工具/系统来源信息,例如来自其他生态系统组件的相关对象的URL。 31 | - 轻量级升级工具的元数据:例如配置或检查点。 32 | - 负责人的电话或寻呼机号码,或指定能找到该信息的条目,例如团队网站。 33 | 34 | 如果不使用注释,则可将这种类型的信息存储在外部数据库或目录中,但这将会使生产共享客户端库/工具(用于部署、管理、内省)变得更加困难。 35 | 36 | 37 | 38 | ## 原文 39 | 40 | -------------------------------------------------------------------------------- /kubernetes/01-Overview/Working with Kubernetes Objects/Label和Selector.md: -------------------------------------------------------------------------------- 1 | # Label和Selector(Label和选择器) 2 | 3 | *Label*是附加到对象(如Pod)的键值对。Label旨在用于指定对用户有意义的对象的识别属性,但不直接表示核心系统的语义。Label可用于组织和选择对象的子集。Label可在创建时附加到对象,也可在创建后随时添加和修改。每个对象都可定义一组Label。 对于给定的对象,Key必须唯一。 4 | 5 | ```json 6 | "labels" : { 7 | "key1" : "value1" , 8 | "key2" : "value2" 9 | } 10 | ``` 11 | 12 | 我们最终会对Label进行索引和反向索引,以便于高效的查询、watch、排序、分组等操作。不要使用非标识的、大型的结构化数据污染Label。对于非标识的信息应使用非标识,特别是大型和/或结构化数据来污染Label。 非识别信息应使用 [annotation](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) 记录。 13 | 14 | 15 | 16 | 17 | 18 | ## 动机 19 | 20 | Label使用户能够以松耦合的方式,将自己的组织结构映射到系统对象上,客户端无需存储这些映射。 21 | 22 | 服务部署和批处理流水线通常是多维实体(例如:多个分区或部署、多个发布轨道、多个层、每层有多个微服务)。管理往往需要跨部门才能进行,这打破了严格层级表现的封装,特别是由基础设施而非用户确定的刚性层次结构。 23 | 24 | 示例Label: 25 | 26 | - `"release" : "stable"`, `"release" : "canary"` 27 | - `"environment" : "dev"`, `"environment" : "qa"`, `"environment" : "production"` 28 | - `"tier" : "frontend"`, `"tier" : "backend"`, `"tier" : "cache"` 29 | - `"partition" : "customerA"`, `"partition" : "customerB"` 30 | - `"track" : "daily"`, `"track" : "weekly"` 31 | 32 | 以上只是常用Label示例。可自由定制。请记住,给定对象的Label的key必须唯一。 33 | 34 | 35 | 36 | 37 | 38 | ## 语法和字符集 39 | 40 | *Label*是键值对的形式。 41 | 42 | 有效Label的key分为两段: 43 | 44 | * 名称段和前缀段,以 `/` 分隔。 45 | * 名称段是必需的,不超过63个字符,以字母或数字( `[a-z0-9A-Z]` )开头和结尾,中间可包含 `-` 、 `_` 、 `.` 、字母或数字等字符。 46 | * 前缀段是可选的。必须是DNS子域:一系列由 `.` 分隔的DNS Label,总共不超过253个字符,后跟 `/` 。 47 | * 如省略前缀,则假定Label的Key对用户是私有的。 48 | * 为最终用户对象添加Label的自动化系统组件(例如, `kube-scheduler` 、 `kube-controller-manager` 、`kube-apiserver` 、 `kubectl` 或其他第三方自动化组件)必须指定前缀。 `kubernetes.io/` 前缀保留给Kubernetes核心组件。 49 | 50 | 51 | 有效的Label值必须: 52 | 53 | * 不超过63个字符 54 | * 为空,或者:以字母或数字( `[a-z0-9A-Z]` )开头和结尾,中间包含 `-` 、 `_` 、 `.` 、字母或数字等字符。 55 | 56 | 57 | 58 | 59 | 60 | 61 | ## Label选择器 62 | 63 | 不同于 [names and UIDs](https://kubernetes.io/docs/user-guide/identifiers) ,Label不提供唯一性。一般来说,多个可对象携带相同的Label。 64 | 65 | 通过*Label选择器* ,客户端/用户可识别一组对象。Label选择器是Kubernetes中的核心分组API。 66 | 67 | API目前支持两种类型的选择器:*equality-based* 和 *set-based* 。Label选择器可由逗号分隔的多个*需求*组成。在多重需求的情况下,必须满足所有需求,因此逗号作为*AND*逻辑运算符。 68 | 69 | 一个empty Label选择器(即一个零需求的选择器)选择集合中的每个对象。 70 | 71 | null Label选择器(仅用于可选的选择器字段)不选择任何对象。 72 | 73 | **注意** :两个Controller的Label选择器不能在命名空间内重叠,否则它们将会产生冲突。 74 | 75 | 76 | 77 | ### *Equality-based* requirement 78 | 79 | *Equality-* or *inequality-based* requirement允许通过LabelKey和Value进行过滤。匹配对象必须满足所有的Label约束,尽管对象可能还有其他Label。允许使用三种运算符:`=` 、 `==` 、 `!=` 。前两个表示*相等* (只是同义),而后者则表示*不相等* 。 例如: 80 | 81 | ```properties 82 | environment = production 83 | tier != frontend 84 | ``` 85 | 86 | 前者选择所有与key = `environment` 并且value = `production` 的资源。后者选择key = `tier` 并且value不等于`frontend` ,以及key不等于`tier` 的所有资源。可使用`,` 过滤是生产环境中(`production` )非前端(`frontend` )的资源:`environment=production,tier!=frontend` 。 87 | 88 | 89 | 90 | ### *Set-based* requirement 91 | 92 | *Set-based* label requirement允许根据一组Value过滤Key。支持三种运算符: `in` 、`notin` 和`exists`(只有Key标识符)。 例如: 93 | 94 | ``` 95 | environment in (production, qa) 96 | tier notin (frontend, backend) 97 | partition 98 | !partition 99 | ``` 100 | 101 | 第一个示例选择Key等于`environment` ,Value等于`production` 或`qa` 的所有资源。 102 | 103 | 第二个示例选择Key等于`tier` ,Value不等于`frontend` 或`backend`,以及所有Key不等于`tier` 的所有资源。 104 | 105 | 第三个示例选择Key包含`partition` 所有资源;不检查Value的值。 106 | 107 | 第四个示例选择Key不包含`partition` 的所有资源,不检查任何值。 108 | 109 | 类似地,逗号可用作*AND*运算符。 因此可用`partition,environment notin (qa)` 过滤 Key = `partition`(无论值)并且`environment` != `qa` 的资源。 基于*集合的*Label选择器,也可表示基于等式的Label选择。例如,`environment=production`等同于`environment in (production)` ; 同样,`!=` 等同于`notin` 。 110 | 111 | *Set-based* requirement可以与*equality-based* requirement混合使用。例如: `partition in (customerA, customerB),environment!=qa` 。 112 | 113 | 114 | 115 | 116 | 117 | ## API 118 | 119 | ### LIST与WATCH过滤 120 | 121 | LIST和WATCH操作可指定Label选择器,这样就可以使用查询参数过滤返回的对象集。两种requirement都是允许的(在这里表示,它们将显示在URL查询字符串中): 122 | 123 | - *equality-based* requirement: `?labelSelector=environment%3Dproduction,tier%3Dfrontend` 124 | - *set-based* requirements: `?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29` 125 | 126 | 两种Label选择器都可用于在REST客户端中LIST或WATCH资源。例如,使用`kubectl` 定位`apiserver` 并使用 *equality-based* 的方式可写为: 127 | 128 | ``` 129 | $ kubectl get pods -l environment=production,tier=frontend 130 | ``` 131 | 132 | 或使用*set-based* requirements: 133 | 134 | ``` 135 | $ kubectl get pods -l 'environment in (production),tier in (frontend)' 136 | ``` 137 | 138 | 如上所示,*set-based* requirement表达能力更强。例如,他们可以对Value执行*OR*运算符: 139 | 140 | ``` 141 | $ kubectl get pods -l 'environment in (production, qa)' 142 | 143 | ``` 144 | 145 | 或通过exists操作符,实现restricting negative matching: 146 | 147 | ``` 148 | $ kubectl get pods -l 'environment,environment notin (frontend)' 149 | ``` 150 | 151 | 152 | 153 | ### 在API对象中设置引用 154 | 155 | 一些Kubernetes对象(如 [`services`](https://kubernetes.io/docs/user-guide/services) 和 [`replicationcontrollers`](https://kubernetes.io/docs/user-guide/replication-controller) )也可使用Label选择器来指定其他资源(例如 [pods](https://kubernetes.io/docs/user-guide/pods) )。 156 | 157 | 158 | 159 | 160 | 161 | #### Service 和 ReplicationController 162 | 163 | 使用Label选择器定义`service` 指向的一组Pod。类似地, `replicationcontroller` 所管理的Pod总数也可用Label选择器定义。 164 | 165 | 两个对象的Label选择器都使用map在`json` 或`yaml` 文件中定义,只支持*equality-based* requirement选择器: 166 | 167 | ``` 168 | "selector": { 169 | "component" : "redis", 170 | } 171 | 172 | ``` 173 | 174 | 或: 175 | 176 | ``` 177 | selector: 178 | component: redis 179 | ``` 180 | 181 | 此选择器(分别以`json` 或`yaml` 格式)等价于 `component=redis` 或`component in (redis)` 。 182 | 183 | 184 | 185 | #### 支持set-based requirement的资源 186 | 187 | 较新的资源(例如 [`Job`](https://kubernetes.io/docs/concepts/jobs/run-to-completion-finite-workloads/) 、 [`Deployment`](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) 、 [`Replica Set`](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/) 以及 [`Daemon Set`](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) )也支持 *set-based* requirement。 188 | 189 | ```yaml 190 | selector: 191 | matchLabels: 192 | component: redis 193 | matchExpressions: 194 | - {key: tier, operator: In, values: [cache]} 195 | - {key: environment, operator: NotIn, values: [dev]} 196 | ``` 197 | 198 | `matchLabels` 是`{ key,value }` 的映射。 `matchLabels` 映射中的单个`{ key,value }` 等价于`matchExpressions`一个元素,其`key` 为“key”, `operator` 为“In”, `values` 数组仅包含“value”。 `matchExpressions` 是一个Pod选择器需求列表。有效运算符包括In、NotIn、Exists以及DoesNotExist。 当使用In和NotIn时,Value必须非空。所有来自`matchLabels` 和`matchExpressions` 的需求使用AND串联,所有需求都满足才能匹配。 199 | 200 | 201 | 202 | #### 选择Node列表 203 | 204 | 使用Label选择Node的一个用例是约束一个Pod能被调度到哪些Node上。有关详细信息,请参阅有关 [node selection](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) 的文档。 -------------------------------------------------------------------------------- /kubernetes/01-Overview/Working with Kubernetes Objects/Name.md: -------------------------------------------------------------------------------- 1 | # 名称 2 | 3 | Kubernetes REST API中的所有对象都会被Name和UID明确标识。 4 | 5 | 对于用户提供**非唯一**属性,Kubernetes提供 [labels](https://kubernetes.io/docs/user-guide/labels) 和 [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) 来标识。 6 | 7 | 8 | 9 | ## 名称(Name) 10 | 11 | 名称通常由客户提供。对于给定类型的对象,一次只有一个对象可以有一个给定的名称(即:它们在空间上是唯一的)。但是,如果您删除一个对象,则可使用相同的名称创建一个新对象。名称用于引用资源URL中的对象,例如`/api/v1/pods/some-name` 。按照惯例,Kubernetes资源的名称最多可达253个字符,由小写字母、数字、`-` 和`.` 组成,但某些资源有更具体的限制。有关名称的精确语法规则,详见: [identifiers design doc](https://git.k8s.io/community/contributors/design-proposals/architecture/identifiers.md) 。 12 | 13 | 14 | 15 | ## UID 16 | 17 | UID由Kubernetes生成。 在Kubernetes集群的整个生命周期中创建的每个对象都有不同的UID(即:它们在空间和时间上是唯一的)。 -------------------------------------------------------------------------------- /kubernetes/01-Overview/Working with Kubernetes Objects/Namespace.md: -------------------------------------------------------------------------------- 1 | # Namespace(命名空间) 2 | 3 | Kubernetes支持在同一物理集群中创建多个虚拟集群。 这些虚拟集群被称为Namespace。 4 | 5 | 6 | 7 | 8 | 9 | ## 使用多个Namespace的场景 10 | 11 | Namespace旨在用于这种环境:有许多的用户,这些用户分布在多个团队/项目中。对于只有几个或几十个用户的集群,您根本不需要创建或考虑使用Namespace。 当您需要使用Namespace提供的功能时,再考虑使用Namespace。 12 | 13 | Namespace为Name(名称)提供了范围。在Namespace中,资源的名称必须唯一,但不能跨Namespace。 14 | 15 | Namespace是一种在多种用途之间划分集群资源的方法(通过 [resource quota](https://kubernetes.io/docs/concepts/policy/resource-quotas/) )。 16 | 17 | 在未来的Kubernetes版本中,同一Namespace中的对象默认有相同的访问控制策略。 18 | 19 | 没有必要使用多个Namespace来分隔稍微不同的资源,例如同一软件的不同版本,可使用 [labels](https://kubernetes.io/docs/user-guide/labels) 来区分同一Namespace中的资源。 20 | 21 | 22 | 23 | 24 | 25 | ## 使用Namespace 26 | 27 | Namespace的创建和删除在 [Admin Guide documentation for namespaces](https://kubernetes.io/docs/admin/namespaces) 有描述。 28 | 29 | 30 | 31 | ### 查看Namespace 32 | 33 | 可使用如下命令列出集群中当前的Namespace: 34 | 35 | ```Shell 36 | $ kubectl get namespaces 37 | NAME STATUS AGE 38 | default Active 1d 39 | kube-system Active 1d 40 | ``` 41 | 42 | Kubernetes初始有两个Namespace: 43 | 44 | - `default` :对于没有其他Namespace的对象的默认Namespace 45 | - `kube-system` :由Kubernetes系统所创建的对象的Namespace 46 | 47 | 48 | 49 | ### 为请求设置Namespace 50 | 51 | 要临时设置请求的Namespace,可使用`--namespace` 标志。 52 | 53 | 例如: 54 | 55 | ```shell 56 | $ kubectl --namespace= run nginx --image=nginx 57 | $ kubectl --namespace= get pods 58 | ``` 59 | 60 | 61 | 62 | ### 设置Namespace首选项 63 | 64 | 可在上下文中永久保存所有后续`kubectl` 命令的Namespace。 65 | 66 | ```shell 67 | $ kubectl config set-context $(kubectl config current-context) --namespace= 68 | # Validate it 69 | $ kubectl config view | grep namespace: 70 | ``` 71 | 72 | 73 | 74 | 75 | 76 | ## Namespace和DNS 77 | 78 | 当你创建 [Service](https://kubernetes.io/docs/user-guide/services) 时,会创建一个相应的 [DNS entry](https://kubernetes.io/docs/admin/dns) 。此条目的形式为`..svc.cluster.local` ,这意味着如果容器只使用`` ,则它将解析为Namespace本地的服务。 这对在多个Namespace(例如Development、Staging以及Production)中使用相同的配置的场景非常有用。 如果要跨越Namespace,请使用完全限定域名(FQDN)。 79 | 80 | > 译者按:FQDN是fully qualified domain name的缩写,即:完全限定域名 81 | 82 | 83 | 84 | 85 | 86 | ## 并非所有对象都在Namespace中 87 | 88 | 大多数Kubernetes资源(例如:Pod、Service、Replication Controllers等)都在某些Namespace中。但Namespace资源本身并不在Namespace中。低级资源(例如: [nodes](https://kubernetes.io/docs/admin/node) 和persistentVolumes)也不在任何Namespace中。事件是一个例外:它们可能有也可能没有Namespace,具体取决于事件的对象。 89 | 90 | -------------------------------------------------------------------------------- /kubernetes/01-Overview/Working with Kubernetes Objects/理解K8s对象.md: -------------------------------------------------------------------------------- 1 | # 理解K8s对象 2 | 3 | 这个页面描述了Kubernetes对象在Kubernetes API中的表现,以及如何用`.yaml` 格式表达它们。 4 | 5 | 6 | 7 | 8 | 9 | ## 理解Kubernetes对象 10 | 11 | *Kubernetes对象*是Kubernetes系统中的持久实体。Kubernetes使用这些实体来表示集群的状态。具体来说,它们可描述: 12 | 13 | - 容器化的应用程序正在运行什么(以及在哪些Node上运行) 14 | - 这些应用可用的资源 15 | - 这些应用的策略,例如重启策略,升级和容错 16 | 17 | Kubernetes对象是一种“意图记录”——一旦您创建对象,Kubernetes系统将持续工作以确保对象存在。通过创建一个对象,您可以有效地告诉Kubernetes系统您希望集群的工作负载是怎样的?这是您集群的**期望状态** 。 18 | 19 | 要使用Kubernetes对象——无论是创建、修改还是删除它们,您都需要使用 [Kubernetes API](https://git.k8s.io/community/contributors/devel/api-conventions.md) 。 例如,当您使用`kubectl` 命令行时,CLI会为您提供必要的Kubernetes API调用;您也可直接在自己的程序中使用Kubernetes API。Kubernetes目前提供了一个`golang` [client library](https://github.com/kubernetes/client-go) ,并且正在开发其他语言的客户端库(如 [Python](https://github.com/kubernetes-incubator/client-python) )。 20 | 21 | 22 | 23 | ### 对象Spec和Status(规格和状态) 24 | 25 | 每个Kubernetes对象都包含两个嵌套的对象字段,它们控制着对象的配置:对象*spec*和对象*status* 。您必须提供*spec* ,它描述了对象*所期望的状态*——您希望对象所具有的特性。*status*描述对象的*实际状态*,由Kubernetes系统提供和更新。在任何时候,Kubernetes Control Plane都会主动管理对象的实际状态,从而让其匹配你所期望的状态。 26 | 27 | 例如,Kubernetes Deployment是一个表示在集群上运行的应用程序的对象。在创建Deployment时,可设置Deployment spec,例如指定有三个应用程序的replicas(副本)正在运行。这样,Kubernetes系统就会读取Deployment spec,并启动您想要的、应用程序的三个实例——根据您的spec更新status。如果任何一个实例失败(status发生改变),Kubernetes系统就会响应spec和status之间的差异,并进行更正——在这本例中,会启动一个替换实例。 28 | 29 | 有关对象spec,status和metadata的更多信息,详见: [Kubernetes API Conventions](https://git.k8s.io/community/contributors/devel/api-conventions.md) 。 30 | 31 | 32 | 33 | ### 描述Kubernetes对象 34 | 35 | 在Kubernetes中创建对象时,必须提供对象的spec,spec描述对象所期望的状态,以及一些关于对象的基本信息(如名称)。当您使用Kubernetes API创建对象(直接或通过`kubectl` )时,该API请求必须在请求体中包含该信息(以JSON格式)。 **最常见的,可在一个.yaml文件中向kubectl提供信息。** 在进行API请求时, `kubectl` 会将信息转换为JSON。 36 | 37 | 如下是一个示例`.yaml` 文件,显示Kubernetes Deployment所需的字段和对象spec: 38 | 39 | ```Yaml 40 | apiVersion: apps/v1beta1 41 | kind: Deployment 42 | metadata: 43 | name: nginx-deployment 44 | spec: 45 | replicas: 3 46 | template: 47 | metadata: 48 | labels: 49 | app: nginx 50 | spec: 51 | containers: 52 | - name: nginx 53 | image: nginx:1.7.9 54 | ports: 55 | - containerPort: 80 56 | ``` 57 | 58 | 使用该`.yaml` 文件创建Deployment的一种方法是在`kubectl` 命令行界面中使用 [`kubectl create`](https://kubernetes.io/docs/user-guide/kubectl/v1.8/#create) 命令,将`.yaml`文件作为参数传递。 例如: 59 | 60 | ```shell 61 | $ kubectl create -f docs/user-guide/nginx-deployment.yaml --record 62 | ``` 63 | 64 | 将会输出类似如下的内容: 65 | 66 | ``` 67 | deployment "nginx-deployment" created 68 | ``` 69 | 70 | 71 | 72 | ### 必填字段 73 | 74 | 在Kubernetes对象的`.yaml` 文件中,您需要为以下字段设置值: 75 | 76 | - `apiVersion` ——指定Kubernetes API的版本 77 | - `kind` ——你想创建什么类型的对象 78 | - `metadata` ——有助于唯一标识对象的数据,包括`name` 字符串,UID和可选的`namespace` 79 | 80 | 您还需要提供`spec` 字段。对于不同的Kubernetes对象来说, `spec`的格式都是不同的。 [Kubernetes API reference](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) 可帮助您找到所有对象的spec格式。 81 | 82 | 83 | 84 | ## 原文 85 | 86 | -------------------------------------------------------------------------------- /kubernetes/01-Overview/什么是K8s.md: -------------------------------------------------------------------------------- 1 | # 什么是kubernetes 2 | 3 | Kubernetes是一个[旨在自动部署、扩展和运行应用容器的开源平台](http://www.slideshare.net/BrianGrant11/wso2con-us-2015-kubernetes-a-platform-for-automating-deployment-scaling-and-operations) 。 4 | 5 | 使用Kubernetes,您可以快速有效地回应客户需求: 6 | 7 | - 快速、可预测地部署应用。 8 | - 动态缩放您的应用。 9 | - 无缝地推出新功能。 10 | - 仅对需要的资源限制硬件的使用 11 | 12 | 我们的目标是构建一个生态系统,提供组件和工具以减轻在公共和私有云中运行应用程序的负担。 13 | 14 | 15 | 16 | #### Kubernetes是 17 | 18 | - **可移植**: 共有、私有、混合、多云 19 | - **可扩展**: 模块化、可插拔、提供Hook、可组合 20 | - **自愈**: 自动放置、自动重启、自动复制、自动缩放 21 | 22 | Google于2014年启动了Kubernetes项目。Kubernetes建立在[Google在大规模运行生产工作负载方面](https://research.google.com/pubs/pub43438.html) 十几年的经验之上,并结合了社区中最佳的创意和实践。 23 | 24 | 25 | 26 | ## 为什么使用容器 27 | 28 | 寻找你为啥要使用[容器](https://aucouranton.com/2014/06/13/linux-containers-parallels-lxc-openvz-docker-and-more/) 的原因? 29 | 30 | ![](images/why_containers.svg) 31 | 32 | 部署应用程序的*旧方法*是使用操作系统的软件包管理器在主机上安装应用程序。这种方式,存在可执行文件、配置、库和生命周期与操作系统相互纠缠的缺点。人们可构建不可变的虚拟机映像,从而实现可预测的升级和回滚,但VM是重量级、不可移植的。 33 | 34 | *新方法*是部署容器,容器基于操作系统级别的虚拟化而不是硬件虚拟化。这些容器彼此隔离并且与宿主机隔离:它们有自己的文件系统,看不到对方的进程,并且它们的计算资源使用可以被界定。它们比VM更容易构建,并且由于它们与底层基础架构和宿主机文件系统解耦了,可实现跨云、跨操作系统的移植。 35 | 36 | 由于容器小而快,因此可在每个容器镜像中包装一个应用程序。这种一对一的应用到镜像关系解锁了容器的全部优势。使用容器,可以在构建/发布期间(而非部署期间)创建不可变的容器镜像,因为每个应用程序无需与其余的应用程序栈组合,也无需与生产基础架构环境结合。 在构建/发布期间生成容器镜像使得从开发到生产都能够保持一致的环境。 同样,容器比虚拟机更加透明、便于监控和管理——特别是当容器进程的生命周期由基础架构管理而非容器内隐藏的进程监控程序管理时。 最后,通过在每个容器中使用单个应用程序的方式,管理容器无异于管理应用程序的部署。 37 | 38 | 容器好处概要: 39 | 40 | - **灵活的应用创建和部署** :与VM映像相比,容器镜像的创建更加容易、有效率。 41 | - **持续开发,集成和部署** :通过快速轻松的回滚(由于镜像的不可变性)提供可靠且频繁的容器镜像构建和部署。 42 | - **Dev和Ops分离问题** :在构建/发布期间而非部署期间创建镜像,从而将应用程序与基础架构分离。 43 | - **开发、测试和生产环境一致** :在笔记本电脑运行与云中一样。 44 | - **云和操作系统可移植性** :可运行在Ubuntu、RHEL、CoreOS、内部部署,Google Container Engine以及任何其他地方。 45 | 46 | 47 | - **以应用为中心的管理**:从在虚拟硬件上运行操作系统的抽象级别,提升到使用逻辑资源在操作系统上运行应用程序的级别。 48 | - **松耦合,分布式,弹性,解放的微服务**:应用程序分为更小、独立的部件,可动态部署和管理——而不是一个运行在一个大型机上的单体。 49 | - **资源隔离**:可预测的应用程序性能。 50 | - **资源利用**:效率高,密度高。 51 | 52 | 53 | 54 | #### 为什么我需要Kubernetes,它能干啥? 55 | 56 | 最基本的功能:Kubernetes可在物理机或虚拟机集群上调度和运行应用容器。然而,Kubernetes还允许开发人员将物理机以及虚拟机 “从**主机为中心的**基础设施转移到以**容器为中心的**基础设施”,从而提供容器固有的全部优势。 Kubernetes提供了构建**以容器为中心的**开发环境的基础架构。 57 | 58 | Kubernetes满足了在生产中运行的应用程序的一些常见需求,例如: 59 | 60 | - [Co-locating helper processes](https://kubernetes.io/docs/concepts/workloads/pods/pod/) ,促进组合应用程序和保留”一个应用程序的每个容器“模型 61 | - [Mounting storage systems](https://kubernetes.io/docs/concepts/storage/volumes/) 62 | - [Distributing secrets](https://kubernetes.io/docs/concepts/configuration/secret/) 63 | - [Checking application health](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/) 64 | - [Replicating application instances](https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/) 65 | - [Using Horizontal Pod Autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) 66 | - [Naming and discovering](https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/) 67 | - [Balancing loads](https://kubernetes.io/docs/concepts/services-networking/service/) 68 | - [Rolling updates](https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller/) 69 | - [Monitoring resources](https://kubernetes.io/docs/tasks/debug-application-cluster/resource-usage-monitoring/) 70 | - [Accessing and ingesting logs](https://kubernetes.io/docs/concepts/cluster-administration/logging/) 71 | - [Debugging applications](https://kubernetes.io/docs/tasks/debug-application-cluster/debug-application-introspection/) 72 | - [Providing authentication and authorization](https://kubernetes.io/docs/admin/authorization/) 73 | 74 | 这提供了PaaS的简单性,并具有IaaS的灵活性,并促进了跨基础架构提供商的可移植性。 75 | 76 | 77 | 78 | #### Kubernetes是一个怎样的平台? 79 | 80 | 尽管Kubernetes提供了大量功能,但总有新的场景从新功能中受益。应用程序特定的工作流程可被简化,从而加快开发人员的速度。可接受的特别编排最初常常需要大规模的自动化。这就是为什么Kubernetes也被设计为提供构建组件和工具的生态系统,使其更容易部署,扩展和管理应用程序。 81 | 82 | [Label](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) 允许用户随心所欲地组织他们的资源。[Annotation](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) 允许用户使用自定义信息来装饰资源以方便他们的工作流程,并为管理工具提供检查点状态的简单方法。 83 | 84 | 此外, [Kubernetes control plane](https://kubernetes.io/docs/concepts/overview/components/) 所用的[API](https://kubernetes.io/docs/reference/api-overview/) 与开发人员和用户可用的API相同。用户可以使用 [their own API](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/extending-api.md) 编写自己的控制器,例如 [scheduler](https://github.com/kubernetes/community/blob/master/contributors/devel/scheduler.md) ,这些API可由通用 [command-line tool](https://kubernetes.io/docs/user-guide/kubectl-overview/) 定位。 85 | 86 | 这种 [design](https://git.k8s.io/community/contributors/design-proposals/architecture/principles.md) 使得许多其他系统可以构建在Kubernetes上。 87 | 88 | 89 | 90 | #### Kubernetes不是什么? 91 | 92 | Kubernetes不是一个传统的,全面的PaaS系统。 它保留了用户的重要选择。 93 | 94 | Kubernetes: 95 | 96 | - 不限制支持的应用类型。不规定应用框架(例如 [Wildfly](http://wildfly.org/) ),不限制支持的语言运行时(例如Java,Python,Ruby),不局限于 [12-factor applications](https://12factor.net/) ,也不区分*应用程序*和*服务* 。 Kubernetes旨在支持各种各样的工作负载,包括无状态、有状态以及数据处理工作负载。 如果应用程序可在容器中运行,那么它应该能够很好地在Kubernetes上运行。 97 | 98 | 99 | - 不提供中间件(例如消息总线)、数据处理框架(例如Spark)、数据库(例如MySQL),也不提供分布式存储系统(例如Ceph)作为内置服务。 这些应用可在Kubernetes上运行。 100 | 101 | 102 | - 没有点击部署的服务市场。 103 | 104 | 105 | - 不部署源代码,并且不构建应用。持续集成(CI)工作流是一个不同用户/项目有不同需求/偏好的领域,因此它支持在Kubernetes上运行CI工作流,而不强制工作流如何工作。 106 | 107 | 108 | - 允许用户选择其日志记录、监视和警报系统。(它提供了一些集成。) 109 | - 不提供/授权一个全面的应用配置语言/系统(例如 [jsonnet](https://github.com/google/jsonnet) )。 110 | - 不提供/不采用任何综合的机器配置、维护、管理或自愈系统。 111 | 112 | 另一方面,一些PaaS系统可运行*在* Kubernetes上,例如 [Openshift](https://www.openshift.org/) 、 [Deis](http://deis.io/) 、[Eldarion](http://eldarion.cloud/) 等。 您也可实现自己的定制PaaS,与您选择的CI系统集成,或者仅使用Kubernetes部署容器。 113 | 114 | 由于Kubernetes在应用层面而非硬件层面上运行,因此它提供了PaaS产品通用的功能,例如部署,扩展,负载均衡,日志和监控。然而,Kubernetes并不是一个单体,这些默认解决方案是可选、可插拔的。 115 | 116 | 另外Kubernetes不仅仅是一个*编制系统* 。实际上,它消除了编制的需要。编制的技术定义,就是执行定义的工作流:首先执行A,然后B,然后执行C。**相反,Kubernetes由一组独立、可组合的控制进程组成,这些控制进程可将当前状态持续地驱动到所需的状态。** 如何从A到C不要紧,集中控制也不需要;这种做法更类似于*编排* 。 这使系统更易用、更强大,更具弹性和可扩展性。 117 | 118 | > 译者按:编排和编制: 119 | 120 | 121 | 122 | #### *Kubernetes*的含义是什么?K8S呢? 123 | 124 | **Kubernetes**源自希腊语,意思是*舵手*或*飞行员* ,是*governor(掌舵人)* 和[cybernetic(控制论)](http://www.etymonline.com/index.php?term=cybernetics) 的根源。 *K8s*是将8个字母“ubernete”替换为“8”的缩写。 125 | 126 | > 译者按:控制论简介(讲解了什么是governor&cybernetic): 127 | 128 | 129 | 130 | 131 | 132 | ## 原文 133 | 134 | -------------------------------------------------------------------------------- /kubernetes/02-Kubernetes Architecture/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/02-Kubernetes Architecture/.DS_Store -------------------------------------------------------------------------------- /kubernetes/02-Kubernetes Architecture/K8s架构及基本概念.md: -------------------------------------------------------------------------------- 1 | # K8s架构及基本概念 2 | 3 | ## 架构图 4 | 5 | ![](images/k8s-architecture.png) 6 | 7 | 8 | 9 | ## Master(主节点) 10 | 11 | K8s里的Master指是集群控制节点,一个K8s集群需要有一个Master节点来负责整个集群的管理和控制,一般来说,K8s的所有控制命令都是发送给Master,然后由Master来负责具体的执行过程。 12 | 13 | Master通常会部署在一个独立的服务器或虚拟机上,它是整个集群的首脑,如果Master宕机或不可用,那么我们所有的控制命令都将会失效。 14 | 15 | Master节点上运行着如下的关键进程: 16 | 17 | * API Server:K8s里所有资源增删改查等操作的对外入口,也是集群控制的入口进程,它提供了HTTP RESTful API接口给客户端以及其他组件调用。 18 | * Controller Manager:Controller Manager是K8s里所有对象的自动化控制中心。顾名思义,它负责管理“Controller”,主要有: 19 | * endpoint-controller:刷新服务和pod 的关联信息 20 | * replication-controller:维护某个 pod 的副本数为配置的数值 21 | * Scheduler:负责资源调度(Pod调度),将Pod分配到某个节点上。 22 | * [可能有]etcd:资源对象存储中心,K8s的所有资源对象数据都存储在此。 23 | 24 | 25 | 26 | 27 | 28 | 29 | ## Node(工作节点) 30 | 31 | 在K8s集群中,除Master以外的其他机器被称为Node节点。与Master一样,Node节点也可以是一台物理机或虚拟机。 32 | 33 | 由于Node节点才是K8s集群中的工作 34 | 35 | * kubelet:负责Pod所对应的容器的生命周期管理,例如容器的创建、启停等。根据从etcd中获取的信息来管理容器、上报Pod运行状态等。 36 | * kube-proxy:实现K8s Service的通信与负载均衡机制。 37 | * docker:你懂的 38 | 39 | 40 | 41 | 42 | 43 | 44 | ## Pod(容器组) 45 | 46 | Pod是由若干容器组成的容器组,同一个Pod内的所有容器运行在同一主机上,这些容器使用相同的网络命令空间、IP地址和端口,相互之间能通过localhost来发现和通信。 47 | 48 | 不仅如此,同一个Pod内的所有容器还共享存储卷,这个存储卷也被称为Pod Volume。 49 | 50 | 在k8s中创建,**调度和管理的最小单位就是Pod**,而非容器,Pod通过提供更高层次的抽象,提供了更加灵活的部署和管理模式。 51 | 52 | 53 | 54 | 55 | 56 | ## Replication Controller(RC) 57 | 58 | RC是用来管理Pod的工具,每个RC由一个或多个Pod组成。 59 | 60 | * 在RC被创建之后,系统将会保持RC中可用的Pod个数与创建RC时定义的Pod个数一致。 61 | * 如果Pod个数小于定义的个数,RC会启动新的Pod 62 | * 反之则会杀死多余的Pod。 63 | 64 | 我们常会使用YAML定义一个RC,例如: 65 | 66 | ```yaml 67 | apiVersion: v1 # API版本 68 | kind: ReplicationController # 定义一个RC 69 | metadata: 70 | name: mysql # RC名称,全局唯一 71 | spec: 72 | replicas: 1 73 | selector: 74 | app: mysql # RC的POD标签选择器,即:监控和管理拥有这些标签的POD实例,确保当前集群中有且只有replicas个POD实例在运行 75 | template: 76 | metadata: 77 | labels: # 指定该POD的标签 78 | app: mysql # POD副本拥有的标签,需要与RC的selector一致 79 | spec: 80 | containers: 81 | - name: mysql 82 | image: mysql 83 | ports: 84 | - containerPort: 3306 85 | env: 86 | - name: MYSQL_ROOT_PASSWORD 87 | value: "123456" 88 | ``` 89 | 90 | 如上所示,一个RC的定义一般包含了如下三部分: 91 | 92 | * Pod所期待的副本数 93 | * 筛选Pod的标签选择器:RC通过Label来关联对应的Pod 94 | * Pod模板:当集群中Pod的副本数量小于(大于)期望值时,K8s就会使用该模板去创建(删除)新的Pod。 95 | 96 | 97 | 98 | 99 | 100 | 101 | ## Service 102 | 103 | Service可以简单理解成一组提供相同服务的Pod的对外访问入口。Service与Pod之间通过Selector来绑定。下图简单说明了Service与Pod之间的关系 104 | 105 | ![](images/service-pod.png) 106 | 107 | **提问**:RC、Pod、Service三者之间的关系是怎样的? 108 | 109 | 110 | 111 | 112 | 113 | ## 参考文档 114 | 115 | 容器Docker与kubernetes: 116 | 117 | Kubernetes扫盲: 118 | 119 | Kubernetes微服务架构应用实践: 120 | 121 | -------------------------------------------------------------------------------- /kubernetes/02-Kubernetes Architecture/Master与Node的通信.md: -------------------------------------------------------------------------------- 1 | # Master与Node的通信 2 | 3 | ## 概要 4 | 5 | 本文列出了Master(其实是apiserver)和Kubernetes集群之间的通信路径。目的是允许用户自定义其安装,从而加强网络配置,以便集群可在不受信任的网络(或云提供商上的公共IP)上运行。 6 | 7 | 8 | 9 | 10 | 11 | ## Cluster -> Master 12 | 13 | 从集群到Master的所有通信路径终止于apiserver(其他Master组件都不是设计来暴露远程服务的)。在典型的部署中,我们会为apiserver配置监听启用了一种或多种形式的客户端 [authentication](https://kubernetes.io/docs/admin/authentication/) 的安全HTTPS端口(443)。应启用一种或多种 [authorization](https://kubernetes.io/docs/admin/authorization/) 形式,特别是允许 [anonymous requests](https://kubernetes.io/docs/admin/authentication/#anonymous-requests) 或 [service account tokens](https://kubernetes.io/docs/admin/authentication/#service-account-tokens) 的情况下 14 | 15 | 应为Node配置集群的公共根证书,以便安全地连接到apiserver。例如,在默认的GCE部署中,提供给kubelet的客户端凭证采用客户端证书的形式。请参阅用于自动配置kubelet客户端证书的 [kubelet TLS bootstrapping](https://kubernetes.io/docs/admin/kubelet-tls-bootstrapping/) 。 16 | 17 | 希望连接到apiserver的Pod可通过服务帐户安全地进行,这样,Kubernetes就会在实例化时,自动将公共根证书和有效的承载令牌注入到该Pod中。 `kubernetes` 服务(在所有namespace中)配置了一个虚拟IP地址(通过kube-proxy)重定向到apiserver上的HTTPS端点。 18 | 19 | Master组件通过不安全(未加密或验证)端口与集群apiserver通信。该端口通常仅在Master机器上的localhost接口上公开,以便所有运行在同一台机器上的Master组件可与集群的apiserver进行通信。 随着时间的推移,Master组件将被迁移以使用安全端口进行认证和授权(参见 [#13598](https://github.com/kubernetes/kubernetes/issues/13598) )。 20 | 21 | 因此,默认情况下,来自集群(Node,以及Node上运行的Pod)到Master的连接的默认操作模式将被保护,并且可在不可信和/公共网络上运行。 22 | 23 | 24 | 25 | 26 | 27 | ## Master -> Cluster 28 | 29 | 从Master(apiserver)到集群主要有两个通信路径。一是从apiserver到集群中的每个Node上运行的kubelet进程。二是通过apiserver的proxy功能,从apiserver到任意Node、Pod、或Service。 30 | 31 | 32 | 33 | ### apiserver - > kubelet 34 | 35 | 从apiserver到kubelet的连接用于: 36 | 37 | - 获取Pod的日志。 38 | - 通过kubectl连接到运行的Pod。 39 | - 提供kubelet的端口转发功能。 40 | 41 | 这些连接终止于kubelet的HTTPS端点。默认情况下,apiserver不验证kubelet的证书,这使得连接可能会受到中间人的攻击,并且在不可信/公共网络上运行是不安全的。 42 | 43 | 要验证此连接,请使用`--kubelet-certificate-authority` 标志,为apiserver提供一个根证书包,用于验证kubelet的证书。 44 | 45 | 如果不能这样做,如果需要,请在apiiserver和kubelet之间使用 [SSH tunneling](https://kubernetes.io/docs/concepts/architecture/master-node-communication/#ssh-tunnels) ,以避免通过不可信或公共网络进行连接。 46 | 47 | 最后,应启用 [Kubelet authentication and/or authorization](https://kubernetes.io/docs/admin/kubelet-authentication-authorization/) 来保护kubelet API。 48 | 49 | 50 | 51 | ### apiserver -> nodes, pods, and services 52 | 53 | 从apiserver到Node、Pod或Service的连接默认为纯HTTP连接,因此不会被认证或加密。可通过将`https:` 前缀添加到到API URL中的Node、Pod、Service名称,从而运行安全的HTTPS连接,但不会验证HTTPS端点提供的证书,也不会提供客户端凭据——因此,尽管连接将被加密,它不会提供任何诚信保证。这些连接在不受信任/公共网络上运行**并不安全**。 54 | 55 | 56 | 57 | ### SSH隧道 58 | 59 | [Google Container Engine](https://cloud.google.com/container-engine/docs/) 使用SSH隧道来保护Master -> 集群的通信路径。在此配置中,apiserver会启动一个SSH隧道到集群中的每个Node(连接到监听端口22的ssh服务器),并通过隧道传递目标为kubelet,Node,Pod或Service的所有流量。该隧道确保流量不会暴露到私有GCE网络以外。 60 | 61 | 62 | 63 | ## 原文 64 | 65 | -------------------------------------------------------------------------------- /kubernetes/02-Kubernetes Architecture/Node.md: -------------------------------------------------------------------------------- 1 | # Node(节点) 2 | 3 | 4 | 5 | 6 | 7 | ## 什么是Node? 8 | 9 | `node` 是Kubernetes中的工作机器(worker),以前被称为`minion` 。 集群中的Node可以是VM或物理机。 每个Node上都有运行 [pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/) 所必要的服务,并由Master组件管理。Node上的服务包括Docker、kubelet和kube-proxy。有关更多详细信息,请参阅架构设计文档中的 [The Kubernetes Node](https://git.k8s.io/community/contributors/design-proposals/architecture/architecture.md#the-kubernetes-node) 部分。 10 | 11 | 12 | 13 | 14 | 15 | ## Node状态 16 | 17 | Node状态包含如下信息: 18 | 19 | - Addresses 20 | - Phase 【**弃用**】 21 | - Condition 22 | - Capacity 23 | - Info 24 | 25 | 下面详解每个部分: 26 | 27 | 28 | 29 | 30 | 31 | ### Addresses(地址) 32 | 33 | 这些字段的用法取决于你云提供商或裸机的配置。 34 | 35 | - HostName:Node内核报告的hostname。可通过kubelet的 `--hostname-override` 参数配置。 36 | - ExternalIP:通常是可外部路由的Node IP(可从群集外部获得)。 37 | - InternalIP:通常只能在集群内进行路由的Node IP。 38 | 39 | 40 | 41 | 42 | ### Phase(阶段) 43 | 44 | 已弃用,Node phase不再使用。 45 | 46 | 47 | 48 | ### Condition(状况) 49 | 50 | `conditions` 字段描述所有`Running` Node的状态。 51 | 52 | | Node Condition | Description | 53 | | -------------------- | ---------------------------------------- | 54 | | `OutOfDisk` | 如果节点没有足够的可用空间来添加新的Pod,则为`True` ,否则为`False` | 55 | | `Ready` | 如果节点健康并准备好接受Pod,则为`True` ;如果节点不健康且不接受Pod,则为`False`,如果node controller与Node失联40秒以上,则为“ `Unknown` | 56 | | `MemoryPressure` | 如果node的内存存在压力,则为`True` ——即node内存容量低;否则为`False` | 57 | | `DiskPressure` | 如果磁盘存在压力,则为`True` ——即磁盘容量低;否则为`False` | 58 | | `NetworkUnavailable` | 如果Node的网络未正确配置,则为`True` ,否则为`False` | 59 | 60 | node condition使用JSON对象来表示。 例如,以下描述了一个健康的Node。 61 | 62 | ```json 63 | "conditions": [ 64 | { 65 | "kind": "Ready", 66 | "status": "True" 67 | } 68 | ] 69 | ``` 70 | 71 | 如果`Ready` condition的状态为“Unknown”或“False” ,并且持续超过`pod-eviction-timeout` ,则会将一个参数传递给 [kube-controller-manager](https://kubernetes.io/docs/admin/kube-controller-manager/) ,并且Node上的所有Pod都会被Node Controller驱逐。默认驱逐的超时时间为**五分钟** 。 在某些情况下,当Node不可访问时,apiserver无法与其上的kubelet进行通信。 在与apiserver恢复通信之前,删除Pod的指令无法传达到kubelet。 同时,计划删除的Pod可能会继续在该Node上运行。 72 | 73 | 在Kubernetes 1.5之前,Node Controller将强制从apiserver中 [force delete](https://kubernetes.io/docs/concepts/workloads/pods/pod/#force-deletion-of-pods) 这些不可达的pod。但在1.5及更高版本中,Node Controller不会强制删除Pod,直到确认它们已停止运行。 74 | 75 | 这些不可达Node上运行的Pod会处于“Terminating”或“Unknown”状态。如果Kubernetes无法从底层基础设施推断出Node已永久离开集群,集群管理员可能需要手动删除Node对象。从Kubernetes删除Node对象会导致运行在其上的所有Pod对象从apiserver中删除,并释放其名称。 76 | 77 | Kubernetes 1.8引入了一个自动创建代表condition的 [taints](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) 功能(目前处于Alpha状态)。要启用此特性,请向API server、controller manager和scheduler传递标志`--feature-gates=...,TaintNodesByCondition=true` 。一旦启用 `TaintNodesByCondition` ,scheduler将会忽略选择Node时的condition;而是看Node的taint(污点)和Pod的toleration(容忍度)。 78 | 79 | > 译者按: 80 | > 81 | > 1. “[taints and tolerations](https://kubernetes.io/docs/user-guide/node-selection/#taints-and-toleations-beta-feature)” 的功能是允许你标注(taint)Node,那样Pod就不会调度到这个Node上,除非Pod明确”tolerates”这个”taint”。 82 | > 2. K8s高级调度特性: 83 | 84 | 现在用户可在旧调度模型和新的更灵活的调度模型之间选择。没有toleration(容忍度)的Pod根据旧的模型进行调度。但是,对特定Node能够容忍污点(tolerates the taints)的Pod可被调度到该Node。 85 | 86 | 请注意,由于延迟时间小,通常少于1秒,在观察condition和产生污点的时间段内,启用此功能可能会稍微增加成功调度但被kubelet拒绝的Pod的数量。 87 | 88 | 89 | 90 | ### Capacity(容量) 91 | 92 | 描述Node上可用的资源:CPU、内存,以及可调度到该Node的最大Pod数。 93 | 94 | 95 | 96 | ### Info(信息) 97 | 98 | 关于Node的一般信息,如内核版本、Kubernetes版本(kubelet和kube-proxy版本)、Docker版本(如果使用了Docker的话)、OS名称。信息由Kubelet从Node收集。 99 | 100 | 101 | 102 | 103 | 104 | ## Management(管理) 105 | 106 | 与 [pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/) 、 [services](https://kubernetes.io/docs/concepts/workloads/pods/pod/) 不同,Node不是由Kubernetes创建的:它是由Google Compute Engine等云提供商在外部创建的,或存在于物理机或虚拟机池中。这意味着当Kubernetes创建一个Node时,它只是创建一个表示Node的对象。创建后,Kubernetes将检查Node是否有效。例如,如果您尝试从以下内容创建一个Node: 107 | 108 | ```json 109 | { 110 | "kind": "Node", 111 | "apiVersion": "v1", 112 | "metadata": { 113 | "name": "10.240.79.157", 114 | "labels": { 115 | "name": "my-first-k8s-node" 116 | } 117 | } 118 | } 119 | ``` 120 | 121 | Kubernetes将在内部创建一个Node对象(用来表示Node),并通过基于`metadata.name` 字段的健康检查来验证Node(我们假设`metadata.name` 可以被解析)。如果Node通过验证,即:所有必需的服务都处于运行状态,则它有资格运行Pod;否则,它将被忽略,直到通过验证。 请注意,Kubernetes将保留无效Node的对象,并继续检查它是否有效,除非它被客户端明确删除。 122 | 123 | 目前,有三个组件与Kubernetes Node接口进行交互:node controller、kubelet和kubectl。 124 | 125 | 126 | 127 | 128 | 129 | ### Node Controller 130 | 131 | Node Controller是一个Kubernetes Master组件,管理Node的各个方面。 132 | 133 | Node Controller在Node的生命周期中具有多个角色。首先,是在注册时将CIDR块分配给Node(如果CIDR分配已打开)。 134 | 135 | > 译者按:CIDR(无类别域间路由): 136 | 137 | 其次,是使Node Controller的内部列表与云提供商的可用机器列表同步。在云环境中,每当Node不健康时,Node Controller就会请求云提供商,查询该Node的VM是否依然可用。如果不可用,Node Controller就会从其Node列表中删除该Node。 138 | 139 | 第三,是监视Node的健康状况。当Node变得不可达时,Node Controller负责将NodeStatus的NodeReady condition更新为ConditionUnknown(即:Node Controller由于某些原因停止接收心跳,例如由于Node关闭)。如果Node依然无法访问,那么就会从该Node中驱逐所有Pod (使用优雅关闭的方式)。(Node Controller与Node失联超过40秒,就会报告ConditionUnknown,5分钟后开始驱逐Pod)。Node Controller每隔`--node-monitor-period` 检查一次Node状态。 140 | 141 | 在Kubernetes 1.4中,我们更新了Node Controller的逻辑,从而更好地处理大量Node无法连接Master的情况(例如,由于Master有网络问题)。 从1.4开始,Node Controller在做关于Pod驱逐的决定时,会查看集群中所有Node的状态。 142 | 143 | 在大多数情况下,Node Controller将驱逐速率限制为 `--node-eviction-rate` (默认为0.1)每秒,这意味着它不会1个Node驱逐Pod花费的时间不会超过10秒。 144 | 145 | 当给定可用区(availability zone)中的Node变得不健康时,Node驱逐的行为就会发生变化。Node Controller同时也会检查区域中有多少百分比的Node是不正常的(NodeReady condition是ConditionUnknown或ConditionFalse)。如果不健康Node的阈值达到 `--unhealthy-zone-threshold` (默认为0.55),那么驱逐速率将被降低:如果集群很小(即小于或等于 `--large-cluster-size-threshold` 个Node,默认50),那么驱逐就会停止;否则驱逐速率降低到 `--secondary-node-eviction-rate` (默认0.01)每秒。每个可用区实施这些策略的原因,是因为每个可用区都可能会从Master断开,而另一个可用区仍然保持连接。如果您的集群不会跨越多个云提供商的可用区,那么就只有一个可用区(整个群集)。 146 | 147 | > 译者按:可用区举例:AWS可用区: 148 | 149 | 在可用区之间传播Node的一个关键原因是:当整个区域停止时,工作负载可以转移到健康区域。因此,当一个区域中的所有Node都不健康时,那么Node Controller就以正常速率`--node-eviction-rate` 驱逐。 当所有区域都不健康时(即集群中没有健康的Node),Node Controller就会假定Master的连接有问题,并停止所有驱逐,直到连接恢复。 150 | 151 | 从Kubernetes 1.6开始,NodeController还负责驱逐运行在“NoExecute taint”的Node上的Pod,当Pod不能忍受这些taint时。 另外,作为默认禁用的Alpha功能,NodeController负责添加taint,这些taint与诸如Node可达或未准备好等问题相关。有关NoExecute taint和Alpha功能的详细信息,请参阅 [this documentation](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) 。 152 | 153 | 从1.8版开始,Node Controller可负责创建表示节点condition的taint。这是1.8版的Alpha功能。 154 | 155 | 156 | 157 | ### Node的自注册 158 | 159 | 当kubelet标志`--register-node` 为true(默认值)时,kubelet将会尝试向API server注册自己。这是大多数版本所使用的首选模式。 160 | 161 | 对于自注册,kubelet会使用如下的选项启动: 162 | 163 | - `--kubeconfig` :凭证向apiserver进行身份验证的路径。 164 | - `--cloud-provider` :如何与云提供商进行会话,从而获取自身的元数据。 165 | - `--register-node` :自动向API server注册。 166 | - `--register-with-taints` :注册具有给定taint列表的Node(逗号分隔的`=:` )。 如果`register-node` 为false,则为No-op(空操作,啥都不干)。 167 | - `--node-ip` :Node的IP。 168 | - `--node-labels` :向集群注册Node时添加的标签。 169 | 170 | 171 | - `--node-status-update-frequency` :指定kubelet将Node状态发送到Master的频率。 172 | 173 | 目前,任何kubelet都被授权创建/修改任何Node资源,但实际上只能创建/修改其自身的资源。(将来,我们计划只允许一个kubelet修改自己的Node资源。) 174 | 175 | 176 | 177 | ### 手动管理Node 178 | 179 | 集群管理员可创建和修改Node对象。 180 | 181 | 如果管理员希望手动创建Node对象,可设置kubelet标志`--register-node=false` 。 182 | 183 | 管理员可修改Node资源(忽视`--register-node` 的设置)。修改操作包括:在Node上设置标签,并将其标记为不可调度。 184 | 185 | Node上的Label可与Pod上的Node selector(Node选择器)一起使用,从而控制调度——例如,限制一个Pod只能在指定的节点列表上运行。 186 | 187 | 将Node标记为不可调度,将会阻止新的Pod被调度到该Node,但不会影响Node上的现有的Pod。这对于做Node重启之前的准备工作很有用。例如,要将node标记为不可调度,可使用如下命令: 188 | 189 | ```shell 190 | kubectl cordon $NODENAME 191 | ``` 192 | 193 | **请注意**,由DaemonSet Controller创建的Pod会绕过Kubernetes调度程序,并且不遵循节点上的unschedulable属性。 因为,我们假设daemon进程属于机器,即使在准备重启时正被耗尽。 194 | 195 | 196 | 197 | ### Node容量 198 | 199 | Node的容量(CPU数量和内存大小)是Node对象的一部分。 通常来说,Node在创建Node对象时注册自身,并报告其容量。如果您正在进行 [manual node administration](https://kubernetes.io/docs/concepts/architecture/nodes/#manual-node-administration) ,则需要在添加Node时设置Node容量。 200 | 201 | Kubernetes调度程序可确保Node上的所有pod都有足够的资源。它会检查节点上容器的请求总和不大于Node容量。它包括由kubelet启动的所有容器,但不包括由Docker直接启动的容器,也不包含那些不运行在容器中的进程。 202 | 203 | 如果要明确保留非Pod进程的资源,可创建一个“placeholder pod(占位Pod)”。使用以下模板: 204 | 205 | ```yaml 206 | apiVersion: v1 207 | kind: Pod 208 | metadata: 209 | name: resource-reserver 210 | spec: 211 | containers: 212 | - name: sleep-forever 213 | image: gcr.io/google_containers/pause:0.8.0 214 | resources: 215 | requests: 216 | cpu: 100m 217 | memory: 100Mi 218 | ``` 219 | 220 | 将`cpu` 和`memory` 值设置为您要保留的资源量。将该文件放在清单目录中(kubelet的`--config=DIR` 标志)。 在想要预留资源的每个kubelet上执行此操作。 221 | 222 | 223 | 224 | 225 | 226 | ## API对象 227 | 228 | Node是Kubernetes REST API中的顶级资源。有关API对象的更多详细信息,可详见:[Node API object](https://kubernetes.io/docs/api-reference/v1.8/#node-v1-core) 。 229 | 230 | 231 | 232 | ## 原文 233 | 234 | -------------------------------------------------------------------------------- /kubernetes/02-Kubernetes Architecture/images/k8s-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/02-Kubernetes Architecture/images/k8s-architecture.png -------------------------------------------------------------------------------- /kubernetes/02-Kubernetes Architecture/images/kubernetes-install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/02-Kubernetes Architecture/images/kubernetes-install.png -------------------------------------------------------------------------------- /kubernetes/02-Kubernetes Architecture/images/service-pod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/02-Kubernetes Architecture/images/service-pod.png -------------------------------------------------------------------------------- /kubernetes/05-Workloads/Controllers/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/05-Workloads/Controllers/.DS_Store -------------------------------------------------------------------------------- /kubernetes/05-Workloads/Controllers/Daemon Set.md: -------------------------------------------------------------------------------- 1 | # Daemon Set 2 | 3 | 4 | 5 | 6 | 7 | ## What is a DaemonSet?(什么是DaemonSet?) 8 | 9 | *DaemonSet*确保所有(或一些)Node运行Pod的副本。随着Node被添加到集群,Pod被添加到Node上。随着从集群中删除Node,这些Pods被垃圾回收。删除DaemonSet将清理它创建的Pod。 10 | 11 | DaemonSet的典型用途是: 12 | 13 | - 在每个Node上运行集群存储daemon,例如在每个Node上运行`glusterd` 、 `ceph` 。 14 | - 在每个Node上运行日志收集daemon,例如`fluentd` 或`logstash` 。 15 | - 在每个Node上运行Node监控daemon,如 [Prometheus Node Exporter](https://github.com/prometheus/node_exporter) 、`collectd` 、`Datadog Agent` ,New Relic Agent或Ganglia `gmond` 。 16 | 17 | 在简单的情况下,一个DaemonSet,覆盖所有Node,将用于每种类型的daemon。 更复杂的设置可能对单一类型的daemon使用多个DaemonSet,但对不同硬件类型使用不同标志和/或不同内存和cpu最小需求。 18 | 19 | 20 | 21 | 22 | 23 | ## Writing a DaemonSet Spec(编写DaemonSet Spec) 24 | 25 | 26 | 27 | ### Create a DaemonSet(创建DaemonSet) 28 | 29 | 您可以在YAML文件中描述DaemonSet。 例如,下面的 `daemonset.yaml` 文件描述了运行`fluentd-elasticsearch` Docker镜像的DaemonSet: 30 | 31 | ```yaml 32 | apiVersion: apps/v1beta2 33 | kind: DaemonSet 34 | metadata: 35 | name: fluentd-elasticsearch 36 | namespace: kube-system 37 | labels: 38 | k8s-app: fluentd-logging 39 | spec: 40 | selector: 41 | matchLabels: 42 | name: fluentd-elasticsearch 43 | template: 44 | metadata: 45 | labels: 46 | name: fluentd-elasticsearch 47 | spec: 48 | containers: 49 | - name: fluentd-elasticsearch 50 | image: gcr.io/google-containers/fluentd-elasticsearch:1.20 51 | resources: 52 | limits: 53 | memory: 200Mi 54 | requests: 55 | cpu: 100m 56 | memory: 200Mi 57 | volumeMounts: 58 | - name: varlog 59 | mountPath: /var/log 60 | - name: varlibdockercontainers 61 | mountPath: /var/lib/docker/containers 62 | readOnly: true 63 | terminationGracePeriodSeconds: 30 64 | volumes: 65 | - name: varlog 66 | hostPath: 67 | path: /var/log 68 | - name: varlibdockercontainers 69 | hostPath: 70 | path: /var/lib/docker/containers 71 | ``` 72 | 73 | - 基于YAML文件创建DaemonSet: `kubectl create -f daemonset.yaml` 74 | 75 | 76 | 77 | 78 | ### Required Fields(必填字段) 79 | 80 | 与所有其他Kubernetes配置一样,DaemonSet需要 `apiVersion` , `kind` 和 `metadata` 字段。有关使用配置文件的信息,请参阅 [deploying applications](https://kubernetes.io/docs/user-guide/deploying-applications/) 、[configuring containers](https://kubernetes.io/docs/tasks/) 以及 [working with resources](https://kubernetes.io/docs/concepts/tools/kubectl/object-management-overview/) 。 81 | 82 | DaemonSet还需要一个 [`.spec`](https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status) 部分。 83 | 84 | 85 | 86 | ### Pod Template(Pod模板) 87 | 88 | `.spec.template` 是`.spec` 中必需的字段之一。 89 | 90 | `.spec.template`是一个 [pod template](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/#pod-templates) 。 它与 [Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/) 具有完全相同的模式,只不过它是嵌套的,没有`apiVersion` 或`kind` 。 91 | 92 | 除Pod的必需字段外,DaemonSet中的Pod模板必须指定适当的标签(请参阅 [pod selector](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#pod-selector) )。 93 | 94 | DaemonSet中的Pod模板必须具有等于`Always`的 [`RestartPolicy`](https://kubernetes.io/docs/user-guide/pod-states) ,也可留空,默认为`Always` 。 95 | 96 | 97 | 98 | ### Pod Selector(Pod选择器) 99 | 100 | `.spec.selector` 字段是一个pod选择器。 它的作用与 [Job](https://kubernetes.io/docs/concepts/jobs/run-to-completion-finite-workloads/) 的`.spec.selector` 相同。 101 | 102 | 从Kubernetes 1.8起,您必须指定与 `.spec.template` 的Label相匹配的Pod选择器。如果该字段留空,Pod Selector将不再有默认值。Selector默认与 `kubectl apply` 不兼容。另外,一旦DaemonSet被创建,它的`spec.selector` 就不可变。改变Pod Selector可能会导致Pod的孤立,从而引起用户的困惑。 103 | 104 | `spec.selector` 是由两个字段组成的对象: 105 | 106 | - `matchLabels` - 与 [ReplicationController](https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/) 的`.spec.selector`相同。 107 | - `matchExpressions` - 允许通过指定key列表、value列表、以及与key/value相关联的运算符的方式,来构建更复杂的选择器。 108 | 109 | 当同时指定以上两个字段时,两者之间AND关系。 110 | 111 | 如果指定了`.spec.selector` ,它必须与 `.spec.template.metadata.labels` 匹配。 如果未指定,则默认为相等。 不匹配的配置将会被API拒绝。 112 | 113 | 此外,您通常不应创建其标签与此选择器相匹配的任何Pod,不管是通过另一个DaemonSet还是通过其他Controller(如ReplicaSet)进行匹配。 否则,DaemonSet Controller会认为那些Pod是由它创建的。 Kubernetes不会阻止你这样做。您可能想要执行此操作的一种情况,是手动在一个Node上创建具有不同值的Pod进行测试。 114 | 115 | 如果您尝试创建一个DaemonSet,那么 116 | 117 | // TODO 118 | 119 | 120 | 121 | ### Running Pods on Only Some Nodes(只在一些Node上运行Pod) 122 | 123 | 如果指定了`.spec.template.spec.nodeSelector` ,则DaemonSet Controller将在与该 [node selector](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) 匹配的Node上创建Pod。 同样,如果您指定了`.spec.template.spec.affinity` ,则DaemonSet控制器将在与该 [node affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) 匹配的Node上创建Pod。 如果不指定,则DaemonSet Controller将会在所有Node上创建Pod。 124 | 125 | > 译者按:拓展阅读:《 k8s nodeSelector&affinity》: 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | ## How Daemon Pods are Scheduled(如何调度Daemon Pods) 134 | 135 | 通常,Pod在哪台机器上运行是由Kubernetes Scheduler选择的。但是,由DaemonSet Controller创建的Pod已经事先确定在哪台机器上运行(在创建Pod时指定了`.spec.nodeName` ,因此Scheduler将忽略调度这些Pod)。因此: 136 | 137 | - Node的 [`unschedulable`](https://kubernetes.io/docs/admin/node/#manual-node-administration) 字段不受DaemonSet Controller的约束。 138 | - 即使Scheduler尚未启动,DaemonSet Controller也可以创建Pod,这样设计对集群启动是有帮助的。 139 | 140 | Daemon Pod 关注所设置的 [taints and tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration) 规则,但它们会为如下未指定 `tolerationSeconds` 的taint创建`NoExecute` toleration。 141 | 142 | - `node.kubernetes.io/not-ready` 143 | - `node.alpha.kubernetes.io/unreachable` 144 | 145 | 这样可以确保在启用 `TaintBasedEvictions` alpha功能时,当Node出现问题(如网络分区)时,它们将不被驱逐。(当 `TaintBasedEvictions` 功能未启用时,它们在这些情况下也不会被驱逐,但会NodeController的硬编码行为而被驱逐,而会因为toleration被驱逐)。 146 | 147 | 它们也tolerate以下的 `NoSchedule` taints: 148 | 149 | - `node.kubernetes.io/memory-pressure` 150 | - `node.kubernetes.io/disk-pressure` 151 | 152 | 当启用对critical Pod的支持时,并且DaemonSet中的Pod被标记为critical时,将会创建Daemon pod,Daemon Pod会为 `node.kubernetes.io/out-of-disk` 的taint创建额外 `NoSchedule` 的toleration。 153 | 154 | 请注意,如果启用了Alpha功能 `TaintNodesByCondition` ,上述`NoSchedule` Taints仅在1.8或更高版本中创建。 155 | 156 | 157 | 158 | 159 | 160 | ## Communicating with Daemon Pods(与Daemon Pod通信) 161 | 162 | 与DaemonSet中的Pod通信的方式有: 163 | 164 | - **Push** :配置DaemonSet中的Pod,将更新发送到其他Service服务,例如统计数据库。 它们没有客户端。 165 | - **NodeIP and Known Port** :DaemonSet中的Pod可以使用 `hostPort` ,以便通过Node的IP访问Pod。客户能通过某种方式知道Node IP的列表,并知道端口。 166 | - **DNS** :使用相同的Pod选择器创建 [headless service](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services) ,然后使用 `endpoints` 资源或从DNS查询多个A记录发现DaemonSet。 167 | - **Service** :使用相同的Pod选择器创建Service,并使用该Service来访问随机Node上的daemon。 (无法到达特定Node) 168 | 169 | 170 | 171 | 172 | 173 | ## Updating a DaemonSet(更新DaemonSet) 174 | 175 | 如果Node的Label被更改,DaemonSet会立即将Pods添加到新匹配的Node,并从不匹配Node删除Pod。 176 | 177 | 您可以修改DaemonSet创建的Pod。但是,Pod不允许更新所有字段。此外,在下次创建一个Node(即使使用相同的名称)时,DaemonSet Controller依然会使用原始模板。 178 | 179 | 您可以删除DaemonSet。 如果使用`kubectl` 指定`--cascade=false` ,那么Pod将保留在Node上。然后,您可以使用不同的模板创建一个新的DaemonSet。新DaemonSet将识别所有具有匹配的标签的、已存在的Pod。尽管Pod模板并不匹配,但它不会修改或删除这些Pod。您将需要通过删除Pod或删除Node的方式,强制创建新的Pod。 180 | 181 | 在Kubernetes 1.6及更高版本中,您可以在DaemonSet上 [perform a rolling update](https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/) 。 182 | 183 | 未来的Kubernetes版本将支持Node的受控更新。 184 | 185 | 186 | 187 | 188 | 189 | ## Alternatives to DaemonSet(DaemonSet的替代方案) 190 | 191 | ### Init Scripts(初始化脚本) 192 | 193 | 通过在Node上直接启动它们(例如使用`init` 、 `upstartd`或`systemd` ),可以运行daemon进程。这是非常好的。但是,通过DaemonSet运行这些进程有几个优点: 194 | 195 | 196 | - 能够监控和管理daemon进程的日志,就像应用程序一样。 197 | - 相同的配置语言和工具(如Pod模板, `kubectl` )用于daemon和应用程序。 198 | - 未来版本的Kubernetes可能支持 DaemonSet创建的Pod 与 Node升级工作流 之间的集成。 199 | - 在具有资源限制的容器中运行daemon会增强应用容器和daemon隔离性。 当然,也可通过在容器中运行而不在Pod中运行daemon的方式,实现该目标(例如,直接通过Docker启动)。 200 | 201 | 202 | 203 | 204 | ### Bare Pods(裸Pod) 205 | 206 | 可以直接创建Pods,指定Pod运行在特定的Node上。但是,DaemonSet会替换由于任何原因而被删除或终止的Pod,例如在Node故障或Node被中断维护(例如内核升级)的情况下。因此,您应该使用DaemonSet而非单独创建Pod。 207 | 208 | 209 | 210 | ### Static Pods(静态Pod) 211 | 212 | 可通过将文件写入由Kubelet监视的某个目录来的方式来创建Pods。 这些被称为 [static pods](https://kubernetes.io/docs/concepts/cluster-administration/static-pod/) 。 与DaemonSet不同,静态Pod无法使用kubectl或其他Kubernetes API客户端进行管理。静态Pod不依赖于apiserver,这使其在集群启动的情况下很有用。 此外,静态Pod可能在将来会被废弃。 213 | 214 | 215 | 216 | ### Deployments 217 | 218 | DaemonSets类似于 [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment.md) ,因为它们都创建了Pods,并且这些Pod都有不期望终止的进程(例如web服务器,存储服务器)。 219 | 220 | 为无状态服务使用Deployment,例如前端,缩放副本数量和滚动升级比控制Pod运行在哪个主机上要重要得多。 当一个Pod副本始终在所有或某些主机上运行,并需要先于其他Pod启动时,可使用DaemonSet。 221 | 222 | 223 | 224 | 225 | 226 | ## 原文 227 | 228 | -------------------------------------------------------------------------------- /kubernetes/05-Workloads/Pods/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/05-Workloads/Pods/.DS_Store -------------------------------------------------------------------------------- /kubernetes/06-Configuration/Configuration Best Practices.md: -------------------------------------------------------------------------------- 1 | # Configuration Best Practices 2 | 3 | 本文档强调并整合了整个用户指南、入门文档和示例中引入的配置最佳实践。 4 | 5 | 这是一个“活”的文件。如果你想到的东西不在这个名单上,但可能对他人有用,请不要犹豫,提交issue或提交PR(pull request)。 6 | 7 | 8 | 9 | 10 | 11 | ## General Config Tips(常规配置Tips) 12 | 13 | - 定义配置时,指定最新的稳定API版本(当前为v1)。 14 | 15 | - 配置文件应该被推送到集群之前,应存储在版本控制软件中。这样,如果需要,可以快速回滚配置。如果需要,还可以帮助集群重新创建和恢复。 16 | 17 | - 使用YAML而非JSON编写配置文件。尽管这些格式在几乎所有情况下可以互换使用,但YAML往往对用户更加友好。 18 | 19 | - 只要有意义,将相关对象组合成单个文件。一个文件通常比多个文件更容易管理。请参阅 [guestbook-all-in-one.yaml](https://github.com/kubernetes/examples/tree/master/guestbook/all-in-one/guestbook-all-in-one.yaml) 文件作为此语法的示例。 20 | 21 | 还要注意,可以在目录上调用许多`kubectl` 命令,因此您还可以在配置文件所在目录中调用`kubectl create` 。 请参阅下面的更多细节。 22 | 23 | - 不要指定不必要的默认值 - 简单和最小的配置将减少错误。 24 | 25 | - 将对象描述放在Annotation中。 26 | 27 | 28 | 29 | 30 | 31 | 32 | ## “Naked” Pods vs Replication Controllers and Jobs(“裸”Pod vs Replication Controllers/Job) 33 | 34 | - 如果有一个可行的方案替代裸Pod(换句话说:Pod没有绑定到 [replication controller](https://kubernetes.io/docs/user-guide/replication-controller) ),请使用替代方案。 在Node发生故障的情况下,裸Pod将不会被重新调度。 35 | 36 | 除了某些明确的 [`restartPolicy: Never`](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy) 方案外,Replication Controller总是比直接创建Pod更为可取。一个 [Job](https://kubernetes.io/docs/concepts/jobs/run-to-completion-finite-workloads/) 对象(目前处于Beta状态)也可能适合你。 37 | 38 | 39 | 40 | 41 | 42 | 43 | ## Services 44 | 45 | - 通常最好在相应的 [replication controllers](https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/) 之前创建一个 [service](https://kubernetes.io/docs/concepts/services-networking/service/) 。这使得scheduler能够分散构成Service的Pod。 46 | 47 | 您还可以使用此过程来确保至少一个副本在创建许多副本之前起作用: 48 | 49 | 1. 创建Replication Controller而不指定副本(这将会设置replicas = 1); 50 | 2. 创建Service 51 | 3. 然后扩容Replication Controller。 52 | 53 | 54 | - 除非绝对必要,否则不要使用`hostPort` (例如:对于node daemon)。 它指定要在Node上暴露的端口号。当您将Pod绑定到 `hostPort` ,由于端口冲突,调度Pod的数量有限 - 您只能调度与Kubernetes集群中的Node一样多的Pod。 55 | 56 | 如果只需访问端口进行调试,可以使用 [kubectl proxy and apiserver proxy](https://kubernetes.io/docs/tasks/access-kubernetes-api/http-proxy-access-api/) 或 [kubectl port-forward](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) 。 您可以使用 [Service](https://kubernetes.io/docs/concepts/services-networking/service/) 对象进行外部服务访问。 57 | 58 | 如果您需要在特定主机上暴露Pod的端口,请优先使用 [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) Service,再考虑使用 `hostPort` 。 59 | 60 | 61 | - 由于与`hostPort`相同的原因,避免使用 `hostNetwork` 。 62 | - 当您不需要kube-proxy负载均衡时,使用*headless services* 轻松发现服务。 见[headless services](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services) 。 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | ## Using Labels(标签的使用) 71 | 72 | - 定义、使用能够标识应用程序或部署的**语义属性**的 [labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) 。例如,不要将Label附加到一组Pod来显式表示某些Service(例如 `service: myservice` ),或者显式地表示管理Pod的replication controller(例如`controller: mycontroller` ),你应该附加标识语义的Label属性,例如 `{ app: myapp, tier: frontend, phase: test, deployment: v3 }`。 这将允许您选择适用于上下文的对象组——例如,所有标记了`tier: frontend` 的Pod的Service;或“myapp”应用的所有“test”阶段的组件。有关此方法的示例,请参阅 [guestbook](https://github.com/kubernetes/examples/tree/master/guestbook/) 应用程序。 73 | 74 | 可通过简单的、从其选择器中省略特定于发行版的标签,而非更新Service的选择器以完全Replication Controller的选择器的方式,来实现跨越多个部署的Service,例如 [rolling updates](https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller/) 。 75 | 76 | 77 | - 为方便滚动更新,请在Replication Controller名称中包含版本信息,例如作为名称的后缀。 设置`version`标签也很有用。 滚动更新创建一个新的Controller,而不是修改现有的Controller。因此,版本无关的Controller名称可能会有问题。有关更多详细信息,请参阅rolling-update命令中的 [documentation](https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller/) 。 78 | 79 | 请注意, [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) 对象避免了管理Replication Controller `version names`的需要。 对象的期望状态由Deployment描述,如果应用对该spec的更改,则Deployment Controller将以可控的速率,来将实际状态更改为期望状态。(Deployment对象当前是 [`extensions` API Group](https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups) 的一部分。) 80 | 81 | 82 | - 您可以操作Label进行调试。由于Kubernetes Replication Controller和Service使用Label来匹配Pod,因此可通过删除相关Label来删除Controller或Service的Pod。如果您删除现有Pod的Label,其Controller将会创建一个新的Pod来取代它。这是一个有用的方法,用来调试隔离环境中之前“活着”的Pod。请参阅 [`kubectl label`](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) 命令。 83 | 84 | 85 | 86 | 87 | 88 | 89 | ## Container Images(容器镜像) 90 | 91 | - [default container image pull policy](https://kubernetes.io/docs/concepts/containers/images/) 是`IfNotPresent` ,如果镜像已经存在,则会导致 [Kubelet](https://kubernetes.io/docs/admin/kubelet/) 不会拉取镜像的问题。如果您想始终强制拉取镜像,则必须在.yaml文件中指定`Always`的拉取策略( `imagePullPolicy: Always` ),或在镜像上指定 `:latest` 标签。 92 | 93 | 也就是说,如果您指定的镜像不是 `:latest` 标签,例如 `myimage:v1` ,并且更新了有相同标签的镜像,则Kubelet将不会拉取新的镜像。 可通过更新镜像标签时同时更新镜像的标签(例如改为 `myimage:v2` ),并确保您的配置指向正确的版本,从而解决此问题。 94 | 95 | **注意:**在生产中部署容器时,应避免使用 `:latest` 标签,因为这很难跟踪正在运行哪个版本的镜像并且很难回滚。 96 | 97 | 98 | - 要使用特定版本的镜像,可使用其摘要(SHA256)来指定镜像。这种方法保证镜像永远不会更新。有关使用镜像摘要的详细信息,请参阅 [the Docker documentation](https://docs.docker.com/engine/reference/commandline/pull/#pull-an-image-by-digest-immutable-identifier) 。 99 | 100 | 101 | 102 | 103 | 104 | ## Using kubectl(kubectl的使用) 105 | 106 | - 在可能的情况下使用 `kubectl create -f ` 。这将会`` 中查找所有`.yaml` , `.yml`和`.json`文件中查找配置对象,并将其传给`create` 命令。 107 | - 使用`kubectl delete` 而不是 `stop` 。 `delete` 具有`stop` 功能的超集, `stop` 已被弃用。 108 | - 使用kubectl批量操作(通过文件和/或Label)进行get和delete操作。 请参阅 [label selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors)and [using labels effectively](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively) 。 109 | - 使用`kubectl run` 和 `expose` 快速创建和暴露单个容器部署。有关示例,请参阅[quick start guide](https://kubernetes.io/docs/user-guide/quick-start/) 。 110 | 111 | 112 | 113 | 114 | 115 | ## 原文 116 | 117 | -------------------------------------------------------------------------------- /kubernetes/06-Configuration/Pod Priority and Preemption.md: -------------------------------------------------------------------------------- 1 | # Pod Priority and Preemption(Pod优先级和抢占) 2 | 3 | > 本节把priority翻译成优先级,Preemption翻译成抢占。 4 | 5 | 6 | 7 | **特性状态:** `Kubernetes v1.8` alpha 8 | 9 | 在Kubernetes 1.8或更高版本中,[Pods](https://kubernetes.io/docs/user-guide/pods) 有priority的概念。priority表示某个Pod相对于其他Pod的重要性。当一个Pod不能被调度时,Scheduler试图抢占(驱逐)较低priority的Pod,从而使调度处于pending状态的Pod成为可能。 在未来的Kubernetes版本中,priority还将影响Node上资源的驱逐排序。 10 | 11 | **注意:**抢占不遵守PodDisruptionBudget;有关详细信息,请参阅 [the limitations section](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#poddisruptionbudget-is-not-supported) 。 12 | 13 | 14 | 15 | 16 | 17 | ## How to use priority and preemption(如何使用优先级和抢占) 18 | 19 | 要在Kubernetes 1.8中使用priority和preemption,请按照如下步骤操作: 20 | 21 | 1. 启用该功能。 22 | 2. 添加一个或多个PriorityClasses。 23 | 3. 创建Pod,并将 `PriorityClassName` 设为你所添加的PriorityClasses之一。当然,您无需直接创建Pod;通常可将 `PriorityClassName` 添加到集合对象的Pod模板(如Deployment)。 24 | 25 | 以下部分提供有关这些步骤的更多信息。 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ## Enabling priority and preemption(启用优先级和抢占) 34 | 35 | 默认情况下,Kubernetes 1.8中的Pod priority和preemption功能是禁用的。要启用该功能,请为API Server和Scheduler设置此命令行标志: 36 | 37 | ```shell 38 | --feature-gates=PodPriority=true 39 | ``` 40 | 41 | 并为API Server设置此标志: 42 | 43 | ```shell 44 | --runtime-config=scheduling.k8s.io/v1alpha1=true 45 | ``` 46 | 47 | 启用该功能后,您可以创建 [PriorityClasses](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass) 并创建具有 [`PriorityClassName`](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority) 设置的Pods。 48 | 49 | 如果您尝试过该功能后,决定禁用它,那么您必须删除PodPriority命令行标志或将其设置为false,然后重新启动API Server和Scheduler。禁用该功能后,现有的Pod将保留其priority字段,但禁用preemption,priority字段将被忽略;并且,您不能在新Pod中设置PriorityClassName。 50 | 51 | 52 | 53 | 54 | 55 | ## PriorityClass 56 | 57 | PriorityClass是一个non-namespaced对象,它定义了从priority class到priority整数值的映射。该名称在PriorityClass对象元数据的 `name` 字段中指定。该值在必需的 `value` 字段中指定。value值越大,优先级越高。 58 | 59 | PriorityClass对象可以有小于或等于10亿的、任意32位整数值。较大的数字保留给关键系统Pod,这些Pod通常不应该被抢占或被驱逐。 集群管理员应为每个映射创建一个PriorityClass对象。 60 | 61 | PriorityClass还有两个可选字段: `globalDefault` 和 `description` 。对于未设置 `PriorityClassName` 的Pod, `globalDefault` 字段表示该PriorityClass的值。只有一个 `globalDefault=true` 的PriorityClass能够存在于系统中。如果没有设置了 `globalDefault` 的PriorityClass,那么,未设置 `PriorityClassName` 的Pod的优先级为零。 62 | 63 | `description` 字段是一个任意字符串。这是为了告诉集群用户,他们什么时候该使用这个PriorityClass。 64 | 65 | **注1** :如果升级现有集群并启用此功能,则现有Pod的优先级为零。 66 | 67 | **注2** :为Pod动态添加 `globalDefault=true` 的PriorityClass,不会更改现有Pod的优先级。此类PriorityClass的值仅用于添加PriorityClass后创建的Pod。 68 | 69 | > TODO 注2 原文有点歧义,待测试、改进。 70 | 71 | **注3** :如果您删除了PriorityClass,则引用该PriorityClass名称的现有Pod将保持不变,但您无法继续创建引用该PriorityClass名称的Pod。 72 | 73 | 74 | 75 | ### Example PriorityClass 76 | 77 | ```yaml 78 | apiVersion: scheduling.k8s.io/v1alpha1 79 | kind: PriorityClass 80 | metadata: 81 | name: high-priority 82 | value: 1000000 83 | globalDefault: false 84 | description: "This priority class should be used for XYZ service pods only." 85 | ``` 86 | 87 | 88 | 89 | 90 | 91 | ## Pod priority 92 | 93 | 创建一个或多个PriorityClass之后,可创建Pod,并在其spec中指定其中一个PriorityClass名称。priority admission controller使用 `priorityClassName` 字段并填充该字段的整数值。如果未找到priority class,则Pod被拒绝。 94 | 95 | 如下YAML是一个Pod的定义,该Pod使用上述示例中所创建的PriorityClass。priority admission controller检查spec,并将Pod的priority设为1000000。 96 | 97 | ```yaml 98 | apiVersion: v1 99 | kind: Pod 100 | metadata: 101 | name: nginx 102 | labels: 103 | env: test 104 | spec: 105 | containers: 106 | - name: nginx 107 | image: nginx 108 | imagePullPolicy: IfNotPresent 109 | priorityClassName: high-priority 110 | ``` 111 | 112 | 113 | 114 | 115 | 116 | ## Preemption(抢占) 117 | 118 | 当Pods被创建时,它们会进入队列并等待被调度。Scheduler从队列中选择一个Pod,并尝试将其调度到Node上。 如果未能找到满足Pod所有要求的Node,则为处于pending状态的Pod触发preemption逻辑。下面我们称这个处于pending状态的Pod为P。抢占逻辑尝试找到一个Node,在删除一个或多个优先级低于P的Pod后,就能在该Node上调度P。 如果能找到这样的Node,则会从Node中删除一个或多个优先级较低的Pod。 在其删除后,P就能在Node上调度。 119 | 120 | 121 | 122 | ### Limitations of preemption (alpha version) 123 | 124 | #### Starvation of preempting Pod 125 | 126 | 当Pod被抢占时,受害者获得了 [graceful termination period](https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods) 。他们有graceful termination period所定义的时长完成工作并退出。如果无法优雅关闭,就会被杀死。这个graceful termination period会在 scheduler抢占Pod的时间点 与 能在Node(N)上调度pending Pod(P)的时间点 之间创建时间间隔。 在此期间,Scheduler会调度其他pending的Pod。当受害者退出或终止时,Scheduler会尝试调度在待处理队列中的Pod,并且在Scheduler将P调度到N之前,可能会将其中的一个或多个考虑并调度到N。在这种情况下,所有的受害者退出,Pod P不再适用于Node N。因此,Scheduler将必须抢占Node N或其他Node上的其他Pod,以便能够调度P。对于第二次和后续的抢占,这种情况可能会再次重复,P可能会在一定时间内无法得到调度。这种情况可能会导致各种集群中的问题,在Pod创建速率较高的集群中尤其成问题。 127 | 128 | 我们将在Pod preemption的Beta版本中解决这个问题。 [provided here(在这里提供了)](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/pod-preemption.md#preemption-mechanics) 我们计划实施的解决方案。 129 | 130 | #### PodDisruptionBudget is not supported(不支持PodDisruptionBudget) 131 | 132 | [Pod Disruption Budget (PDB)](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/) 允许应用程序所有者限制从voluntary disruptions中资源下降的Pod的数量。 133 | 134 | 然而,在选择preemption的受害者时,alpha版本的preemption并不遵守PDB规则。我们计划在beta版本中添加PDB支持,但即使在beta版中,也只是尽可能地遵守PDB。Scheduler将尝试寻找那些 PDB不会被preemption违反的 受害者,但如果未发现这样的受害者,preemption仍然会发生,优先级较低的Pod将被删除,尽管这会违反PDB。 135 | 136 | > 译者按:PDB简介: 137 | 138 | #### Inter-Pod affinity on lower-priority Pods(低优先级Pod的Inter-Pod 亲和性) 139 | 140 | 在版本1.8中,只有当该问题的答案为yes时,才将Node视为可抢占:“如果从Node中删除所有优先级低于pending Pod的Pod,就能在该Node上调度pending Pod吗? 141 | 142 | **注意:**抢占并不一定会清除所有优先级较低的Pod。如果删除部分优先级较低的Pod就能调度pending Pod,那么只有一部分优先级较低的Pod会被删除。即使如此,上述问题的答案也必须是yes。否则,则Node不被视为可抢占。 143 | 144 | 如果pending Pod具有与 Node上一个或多个较低优先级Pod 的inter-pod affinity,则在那些较低优先级Pod缺失的情况下,不能满足 inter-Pod affinity规则。在这种情况下,Scheduler不会抢占Node上的任何Pod。相反,它寻找另一个Node。 Scheduler可能会找到一个合适的Node,又或者它找不到合适的Node。不能保证pending Pod能够被调度。 145 | 146 | 我们可能会在将来的版本中解决这个问题,但还没有一个明确的计划。我们不会认为它是Beta或GA的阻止者。部分原因是找到满足所有inter-Pod affinity规则的较低优先级的Pod集合,计算代价比较高,并且对抢占逻辑增加了相当大的复杂性。此外,即使preemption保留优先级较低的Pod来满足inter-Pod affinity,较低优先级的Pod也可能被其他Pod稍后抢占,这消除了遵守inter-Pod affinity的复杂逻辑的好处。 147 | 148 | 我们针对此问题的建议解决方案是仅在相同或更高优先级的Pod上创建inter-Pod affinity。 149 | 150 | #### Cross node preemption(跨Node抢占) 151 | 152 | 假设Node N正被考虑用于抢占,以便可在N上调度pending Pod P。只有当另一个Node上的Pod被抢占时,P才可能在N上可行。这里有一个例子: 153 | 154 | - Node N正在考虑Pod P。 155 | - Pod Q在与Node N相同zone中的另一个Node上运行。 156 | - Pod P与Pod Q具有anit-affinity。 157 | - Pod P和其他Pod之间没有anti-affinity的情况。 158 | - 为在Node N上安排Pod P,Pod Q应该被抢占,但是Scheduler不执行跨节点抢占。 所以,Pod P在Node N上被视为unschedulable的。 159 | 160 | 如果Pod Q从其Node中删除,那么久不违反anti-affinity了,并且Pod P可能会在Node N上进行调度。 161 | 162 | 如果我们找到某种性能合理的算法,可能会考虑在将来的版本中添加跨Node抢占。在这一点上我们不能作任何承诺,并且跨Node抢占不会被认为是Beta或GA的阻止者。 163 | 164 | 165 | 166 | 167 | 168 | ## 原文 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /kubernetes/06-Configuration/Secrets.md: -------------------------------------------------------------------------------- 1 | # Secrets 2 | 3 | `secret` 类型的对象旨在保存敏感信息,例如密码、OAuth token和ssh key。将这些信息放在 `secret` 中比放在 `pod` 定义或Docker镜像中更加安全、灵活。有关更多信息,请参阅 [Secrets design document](https://git.k8s.io/community/contributors/design-proposals/auth/secrets.md) 。 4 | 5 | 6 | 7 | 8 | 9 | ## Overview of Secrets(Secret概述) 10 | 11 | Secret是包含少量敏感数据(如密码、token或key)的对象。这样的信息可能会被放在Pod spec或镜像中;将其放在一个Secret对象中能够更好地控制如何使用它,并降低意外暴露的风险。 12 | 13 | 用户可以创建Secret,系统也会创建一些Secret。 14 | 15 | 要使用Secret,Pod需要引用Secret。Secret与Pod一起使用有两种方式:作为mount到一个或多个容器上的 [volume](https://kubernetes.io/docs/concepts/storage/volumes/) 的文件,或在为Pod拉取镜像时由kubelet使用。 16 | 17 | 18 | 19 | ### Built-in Secrets(内置的Secret) 20 | 21 | #### Service Accounts Automatically Create and Attach Secrets with API Credentials(服务帐户自动使用API Credential创建和附加Secret) 22 | 23 | Kubernetes自动创建包含访问API的凭据的Secret,并自动修改您的Pod,让其使用此类型的Secret。 24 | 25 | 如果需要,自动创建和API Credential的使用可禁用或覆盖。但是,如果你只是想安全访问apiserver,默认方式是推荐的工作流程。 26 | 27 | 参阅 [Service Account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) 文档查看其如何工作的更多信息。 28 | 29 | 30 | 31 | 32 | 33 | ### Creating your own Secrets(创建自己的Secret) 34 | 35 | #### Creating a Secret Using kubectl create secret(使用kubectl create secret命令创建Secret) 36 | 37 | 假设Pod需要访问数据库。Pod所使用的用户名和密码在本地机器上的 `./username.txt` 和 `./password.txt` 文件中。 38 | 39 | ```shell 40 | # Create files needed for rest of example. 41 | $ echo -n "admin" > ./username.txt 42 | $ echo -n "1f2d1e2e67df" > ./password.txt 43 | ``` 44 | 45 | `kubectl create secret` 命令可将这些文件打包成一个Secret,并在Apiserver上创建对象。 46 | 47 | ```shell 48 | $ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt 49 | secret "db-user-pass" created 50 | ``` 51 | 52 | 你可以检查这个Secret是如何创建的: 53 | 54 | ```shell 55 | $ kubectl get secrets 56 | NAME TYPE DATA AGE 57 | db-user-pass Opaque 2 51s 58 | 59 | $ kubectl describe secrets/db-user-pass 60 | Name: db-user-pass 61 | Namespace: default 62 | Labels: 63 | Annotations: 64 | 65 | Type: Opaque 66 | 67 | Data 68 | ==== 69 | password.txt: 12 bytes 70 | username.txt: 5 bytes 71 | ``` 72 | 73 | 请注意,默认情况下, `get` 和 `describe` 都不会显示文件的内容。这是为了保护Secret不被意外地暴露。 74 | 75 | 请参阅 [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret/#decoding-a-secret) ,了解如何查看内容。 76 | 77 | #### Creating a Secret Manually(手动创建Secret) 78 | 79 | 您也可以先以json或yaml格式在文件中创建一个Secret对象,然后再创建该对象。 80 | 81 | 每一项都必须以base64进行编码: 82 | 83 | ```shell 84 | $ echo -n "admin" | base64 85 | YWRtaW4= 86 | $ echo -n "1f2d1e2e67df" | base64 87 | MWYyZDFlMmU2N2Rm 88 | ``` 89 | 90 | 现在写一个如下所示的Secret对象: 91 | 92 | ```yaml 93 | apiVersion: v1 94 | kind: Secret 95 | metadata: 96 | name: mysecret 97 | type: Opaque 98 | data: 99 | username: YWRtaW4= 100 | password: MWYyZDFlMmU2N2Rm 101 | ``` 102 | 103 | data字段是一个map。它的key必须符合 [`DNS_SUBDOMAIN`](https://git.k8s.io/community/contributors/design-proposals/architecture/identifiers.md) ,只是也允许leading dots。value是任意数据,使用base64进行编码。 104 | 105 | 使用 [`kubectl create`](https://kubernetes.io/docs/user-guide/kubectl/v1.8/#create) 创建Secret: 106 | 107 | ```shell 108 | $ kubectl create -f ./secret.yaml 109 | secret "mysecret" created 110 | ``` 111 | 112 | **Encoding Note:**Secret数据的值在序列化成JSON或YAML后,被编码为base64字符串。换行符在这些字符串中无效,必须省略。当在Darwin/OS X上使用 `base64` utility时,用户应避免使用 `-b` 选项来拆分非常长的行。相反,Linux用户*应该*添加选项 `-w 0` 到 `base64` 命令;或者管道 `base64 | tr -d '\n'` ,如果 `-w` 选项不可用。 113 | 114 | #### Decoding a Secret(解码Secret) 115 | 116 | Secret可通过 `kubectl get secret` 命令查看。例如,要查看在上一节中创建的Secret: 117 | 118 | ```yaml 119 | $ kubectl get secret mysecret -o yaml 120 | apiVersion: v1 121 | data: 122 | username: YWRtaW4= 123 | password: MWYyZDFlMmU2N2Rm 124 | kind: Secret 125 | metadata: 126 | creationTimestamp: 2016-01-22T18:41:56Z 127 | name: mysecret 128 | namespace: default 129 | resourceVersion: "164619" 130 | selfLink: /api/v1/namespaces/default/secrets/mysecret 131 | uid: cfee02d6-c137-11e5-8d73-42010af00002 132 | type: Opaque 133 | ``` 134 | 135 | 解码password字段: 136 | 137 | ```shell 138 | $ echo "MWYyZDFlMmU2N2Rm" | base64 --decode 139 | 1f2d1e2e67df 140 | ``` 141 | 142 | 143 | 144 | ### Using Secrets(使用Secret) 145 | 146 | Secret可作为数据volume被mount,或作为环境变量暴露,以供Pod中的容器使用。 它们也可被系统的其他部分使用,而不会直接暴露在Pod内。例如,它们可保存系统其他部分应该使用的凭据,从而代表你外部系统进行交互。 147 | 148 | 149 | 150 | 151 | 152 | #### Using Secrets as Files from a Pod(使用Secret作为来自Pod的文件) 153 | 154 | 在Pod中的volume中使用Secret: 155 | 156 | 1. 创建一个secret或使用现有的secret。多个Pod可引用相同的secret。 157 | 2. 修改您的Pod定义,在 `spec.volumes[]` 下添加一个Volume。为Volume任意起个名字,并设置一个 `spec.volumes[].secret.secretName` 字段等于Secret对象的名称。 158 | 3. 将 `spec.containers[].volumeMounts[]` 添加到需要使用Secret的每个容器。 设置`spec.containers[].volumeMounts[].readOnly = true` ,设置 `spec.containers[].volumeMounts[].mountPath` 为您希望显示Secret的未使用的目录名称。 159 | 4. 修改您的镜像和/或命令行,以便程序查找该目录中的文件。 Secret `data` map中的每个key都将成为 `mountPath` 下的文件名。 160 | 161 | 以下是一个在Volume挂载Secret的Pod: 162 | 163 | ```yaml 164 | apiVersion: v1 165 | kind: Pod 166 | metadata: 167 | name: mypod 168 | spec: 169 | containers: 170 | - name: mypod 171 | image: redis 172 | volumeMounts: 173 | - name: foo 174 | mountPath: "/etc/foo" 175 | readOnly: true 176 | volumes: 177 | - name: foo 178 | secret: 179 | secretName: mysecret 180 | ``` 181 | 182 | 你想使用的每个Secret都需要在 `spec.volumes` 中引用。 183 | 184 | 如果Pod中有多个容器,则每个容器都需要自己的 `volumeMounts` ,但每个Secret只需要一个 `spec.volumes` 。 185 | 186 | 您可以将多个文件打包成一个Secret,或使用多个Secret,怎么方便怎么玩。 187 | 188 | **将Secret key投影到特定路径** 189 | 190 | 我们还可控制投影Secret key的Volume。可使用 `spec.volumes[].secret.items` 字段来更改每个key的目标路径: 191 | 192 | ```yaml 193 | apiVersion: v1 194 | kind: Pod 195 | metadata: 196 | name: mypod 197 | spec: 198 | containers: 199 | - name: mypod 200 | image: redis 201 | volumeMounts: 202 | - name: foo 203 | mountPath: "/etc/foo" 204 | readOnly: true 205 | volumes: 206 | - name: foo 207 | secret: 208 | secretName: mysecret 209 | items: 210 | - key: username 211 | path: my-group/my-username 212 | ``` 213 | 214 | 这样: 215 | 216 | - `username` 这个Secret将会存储在 `/etc/foo/my-group/my-username` 文件中,而非 `/etc/foo/username` 。 217 | - `password` 不被投影 218 | 219 | 如使用 `spec.volumes[].secret.items` ,则只会投影 `items` 中指定的key。如果要投影Secret中的所有key,那么所有key都必须列在 `items` 字段中。 所有列出的key必须存在于相应的Secret中。否则,Volume不会被创建。 220 | 221 | **Secret files permissions** (**Secret文件权限**) 222 | 223 | 你也可以指定一个Secret的权限模式位。如不指定,默认使用 `0644` 。可指定整个Secret Volume的默认模式,并根据需要覆盖每个key。 224 | 225 | 例如,你可以指定一个像这样的默认模式: 226 | 227 | ```yaml 228 | apiVersion: v1 229 | kind: Pod 230 | metadata: 231 | name: mypod 232 | spec: 233 | containers: 234 | - name: mypod 235 | image: redis 236 | volumeMounts: 237 | - name: foo 238 | mountPath: "/etc/foo" 239 | volumes: 240 | - name: foo 241 | secret: 242 | secretName: mysecret 243 | defaultMode: 256 244 | ``` 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | // TODO 253 | 254 | Then, the secret will be mounted on `/etc/foo` and all the files created by the secret volume mount will have permission `0400`. 255 | 256 | Note that the JSON spec doesn’t support octal notation, so use the value 256 for 0400 permissions. If you use yaml instead of json for the pod, you can use octal notation to specify permissions in a more natural way. 257 | 258 | You can also use mapping, as in the previous example, and specify different permission for different files like this: 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | ## 原文 268 | 269 | -------------------------------------------------------------------------------- /kubernetes/06-Configuration/Taints and Tolerations.md: -------------------------------------------------------------------------------- 1 | # Taints and Tolerations 2 | 3 | > 译者按: 4 | > 5 | > * Taints:在本文中根据上下文,有的地方直接叫Taints,有的地方翻译成“污点”或者“污染”。 6 | > * Tolerations:在本文中根据上下文,有的地方直接叫Tolerations,有的地方翻译成“容忍”或“容忍度”。 7 | 8 | [here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature) 描述的节点亲和性是一个Pod属性,使用它可将Pod吸引到一组Node(作为优选或硬性要求)。Taint功能相反,它允许Node排斥一组Pod。 9 | 10 | Taints和Tolerations一起工作,以确保Pod不被安排在不适当的Node上。一个或多个Taints应用于Node;这标志着Node不应该接受任何不能容忍这些Taints的Pod。 Tolerations应用于Pod,并允许(但不要求)Pod可以调度到具有匹配Taints的Node上。 11 | 12 | 13 | 14 | 15 | 16 | ## Concepts(概念) 17 | 18 | 您可以使用 [kubectl taint](https://kubernetes.io/docs/user-guide/kubectl/v1.8/#taint) 向节点添加Taint。例如, 19 | 20 | ``` 21 | kubectl taint nodes node1 key=value:NoSchedule 22 | ``` 23 | 24 | 在 `node1` 上设置了一个Taint。Taint具有kay、value以及污点效果`NoSchedule` 。这意味着没有Pod能够调度到`node1` ,除非它具有匹配的Toleration。可在PodSpec中为Pod指定Toleration。以下两种Toleration都与上述`kubectl taint` 所造成的Taint“匹配”,因此这些Pod将能够调度到`node1` 上: 25 | 26 | ```yaml 27 | tolerations: 28 | - key: "key" 29 | operator: "Equal" 30 | value: "value" 31 | effect: "NoSchedule" 32 | ``` 33 | 34 | ```yaml 35 | tolerations: 36 | - key: "key" 37 | operator: "Exists" 38 | effect: "NoSchedule" 39 | ``` 40 | 41 | 如果key相同,并且效果相同,那么Toleration匹配Taint,并且: 42 | 43 | - `operator` 为 `Exists` (在这种情况下不应指定`value` ),或 44 | - `operator` 为 `Equal` 并且 `value` 相等 45 | 46 | 如不指定,则`Operator`默认为 `Equal` 。 47 | 48 | **注意:**有两种特殊情况: 49 | 50 | - `key` 留空配合操作符 `Exists` 可匹配所有key、value和效果,这意味着容忍一切。 51 | 52 | ```yaml 53 | tolerations: 54 | - operator: "Exists" 55 | ``` 56 | 57 | 58 | - `effect` 留空匹配所有带有该`key` 效果。 59 | 60 | ```yaml 61 | tolerations: 62 | - key: "key" 63 | operator: "Exists" 64 | ``` 65 | 66 | 上述示例使用`NoSchedule` 这个 `effect` 。或者,可使用`PreferNoSchedule` 这个 `effect` 。它是 `NoSchedule`的“偏好”或“软”版本——系统将**尽量**避免放置无法容忍Node上Taint的Pod,但不是必需的。 第三种`effect` 是 `NoExecute` ,稍后描述。 67 | 68 | 您可以在同一个Node上设置多个Taint,并在同一个Pod上设置多个Toleration。Kubernetes处理多个Taint和Toleration的方式就像过滤器:从Node的所有Taint开始,然后忽略具有匹配Toleration的那些Pod;剩下的不被忽视的Taints对Pod有明显影响。 尤其是, 69 | 70 | - 如果至少有一个无法忽视的Taint,效果为 `NoSchedule` ,那么Kubernetes不会将Pod调度到该Node上; 71 | - 如果没有不受忽视的Taint,效果为 `NoSchedule` ;但至少有一个无法忽视的Taint,效果为 `PreferNoSchedule` ,那么Kubernetes会将*尝试*不将Pod调度到该Node上; 72 | - 如果至少有一个不受忽视的污点,效果为`NoExecute` ,则该Pod将从Node中驱逐(如果已经在Node上运行),并且不会被调度到该Node上(如果尚未运行在该Node上)。 73 | 74 | 例如,假设你污染了这样一个Node: 75 | 76 | ```shell 77 | kubectl taint nodes node1 key1=value1:NoSchedule 78 | kubectl taint nodes node1 key1=value1:NoExecute 79 | kubectl taint nodes node1 key2=value2:NoSchedule 80 | ``` 81 | 82 | 一个Pod有两个Tolerations: 83 | 84 | ```yaml 85 | tolerations: 86 | - key: "key1" 87 | operator: "Equal" 88 | value: "value1" 89 | effect: "NoSchedule" 90 | - key: "key1" 91 | operator: "Equal" 92 | value: "value1" 93 | effect: "NoExecute" 94 | ``` 95 | 96 | 在本例中,由于没有符合第三个Taint的Toleration,该Pod将无法调度到`node1` 上。但如果在添加Taint时已经在该Node上运行,则能继续运行。 97 | 98 | 通常情况下,如果一个Node添加了一个带有 `NoExecute` 效果的Taint,那么任何不能Toleration该Taint的Pod将立即被驱逐,任何Toleration该Taint的Pod都不会被驱逐。但是,使用 `NoExecute` 效果的Toleration可指定一个可选的 `tolerationSeconds` 字段,该字段表示在添加Taint后,Pod停驻在该Node的时间。例如, 99 | 100 | ```yaml 101 | tolerations: 102 | - key: "key1" 103 | operator: "Equal" 104 | value: "value1" 105 | effect: "NoExecute" 106 | tolerationSeconds: 3600 107 | ``` 108 | 109 | 意味着如果该Pod正在运行,并且Taint被添加到Node,则Pod将在该Node上停驻3600秒,然后被驱逐。 如果在该时间内删除了Taint,则Pod不会被驱逐。 110 | 111 | > 译者按:`tolerationSeconds` 可以理解成:容忍多少秒,过了这么多秒后,就不容忍了,然后就会被驱逐。 112 | 113 | 114 | 115 | 116 | 117 | ## Example Use Cases(使用案例示例) 118 | 119 | Taints和Tolerations是一种能让将Pod”远离“Node或驱逐不应该运行的Pod的方式,该方式非常灵活。一些用例是 120 | 121 | - **Dedicated Nodes(专用Node)** :如果要将一组Node专用于一组特定的用户,您可以向这些Node添加一个污点(例如, `kubectl taint nodes nodename dedicated=groupName:NoSchedule` ),然后将相应的Toleration添加到它们的Pod(这可以通过编写自定义 [admission controller](https://kubernetes.io/docs/admin/admission-controllers/) 来轻松完成)。然后具有Tolerations的Pod将被允许使用污染(专用)Node以及集群中的任何其他Node。如果要将Node专用于它们, 并确保它们**只使用**专用Node,那么您应该额外添加标签,这些标签类似于同一组Node(例如`dedicated=groupName` )上的Taint,并且Admission Controller应该另外添加一个Node的亲和性要求,Pod只能调度到标有 `dedicated=groupName` 的Node上。 122 | 123 | 124 | - **Nodes with Special Hardware(具有特殊硬件的Node)** :在一小部分Node具有专用硬件(例如GPU)的集群中,希望将不需要专用硬件的Pod原理这些Node,从而为需要使用专用硬件的Pod留出空间。这可以通过污染具有专门硬件的Node(例如, `kubectl taint nodes nodename special=true:NoSchedule` 或 `kubectl taint nodes nodename special=true:PreferNoSchedule` )来完成,并将相应的Toleration添加到需使用特殊硬件的Pod。在专用Node的用例中,使用自定义 [admission controller](https://kubernetes.io/docs/admin/admission-controllers/) 应用Tolerations可能是最简单的)。例如,Admission Controller可使用Pod的一些特性来确定应该允许该Pod使用特殊Node。 为确保需要特殊硬件的Pod*只*被调度到具有特殊硬件的Node上,您将需要一些额外的机制,例如您可以使用 [opaque integer resources](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#opaque-integer-resources-alpha-feature) 来表示特殊资源,并将其作为PodSpec中的资源最小需求,或您可以标记具有特殊硬件的Node,并在需要硬件的Pod上使用Node Affinity。 125 | - **Taint based Evictions (alpha feature)(基于Taint的驱逐(alpha功能))** :当Node出现问题时,per-pod-configurable的驱逐行为,这将在下一节中描述。 126 | 127 | 128 | 129 | 130 | 131 | ## Taint based Evictions(基于Taint的驱逐) 132 | 133 | 之前我们提到了`NoExecute` taint的效果,它会影响已经在Node上运行的Pod,如下所示 134 | 135 | - 不能容忍污点的Pod被立即驱逐 136 | - 容忍污点的Pod,而不指定`tolerationSeconds` 将永远被绑定 137 | - 容许污点的Pod,指定`tolerationSeconds` ,在指定的时间内保持绑定 138 | 139 | 上述行为是一个beta功能。 此外,Kubernetes 1.6具有表示Node问题的alpha支持。换句话说,当某些条件为真时,Node Controller会自动给Node添加Taint。 目前内置的Taint包括: 140 | 141 | - `node.kubernetes.io/not-ready` :Node尚未准备就绪。 这对应于NodeCondition `Ready` 字段为 `False` 。 142 | - `node.alpha.kubernetes.io/unreachable` :Node无法从Node Controller访问。这对应于NodeCondition `Ready` 字段为 `Unknown` 。 143 | - `node.kubernetes.io/out-of-disk` :Node磁盘不可用。 144 | - `node.kubernetes.io/memory-pressure` :Node内存有压力。 145 | - `node.kubernetes.io/disk-pressure` :Node磁盘有压力。 146 | - `node.kubernetes.io/network-unavailable` :Node的网络不可用。 147 | - `node.cloudprovider.kubernetes.io/uninitialized` :当kubelet以外部cloud provider启动时,它会为Node设置一个Taint,将其标记为未使用。当来自cloud-controller-manager的Controller初始化此Node时,kubelet将删除此Taint。 148 | 149 | 当启用`TaintBasedEvictions` alpha功能时(您可以通过在Kubernetes controller manager的`--feature-gates` 包含 `TaintBasedEvictions=true`来实现此功能,例如 `--feature-gates=FooBar=true,TaintBasedEvictions=true` ),这样,NodeController(或kubelet)将会自动添加Taint,并且基于Ready NodeCondition从Node驱出Pod的逻辑将会被禁用。(注意:为保持由于Node问题而导致的现有 [rate limiting](https://kubernetes.io/docs/concepts/architecture/nodes/) 行为,系统实际上以rate-limited的方式添加Taints,从而防止在Master节点在发生网络分区故障的场景中有大量的Pod被驱逐。 该alpha特征与`tolerationSeconds`相结合,从而允许Pod指定应该保持绑定到具有这些问题中的Node的时长。 150 | 151 | 例如,具有很多本地状态的应用可能希望在网络分区故障发生的情况下长时间保持绑定到Node,希望分区恢复时避免该驱逐。 在这种情况下,Pod将使用的Toleration情况看起来像: 152 | 153 | ```yaml 154 | tolerations: 155 | - key: "node.alpha.kubernetes.io/unreachable" 156 | operator: "Exists" 157 | effect: "NoExecute" 158 | tolerationSeconds: 6000 159 | ``` 160 | 161 | 请注意,除非用户提供的Pod配置已经具有 `node.kubernetes.io/not-ready` 的Toleration,否则Kubernetes会自动为 `node.kubernetes.io/not-ready` 添加 `tolerationSeconds=300` 的Toleration。 同样地,对于`node.alpha.kubernetes.io/unreachable` ,也会有 `tolerationSeconds=300` 用户自行设置。 162 | 163 | 这些自动添加的Toleration确保在检测到这些问题之一后默认保持绑定5分钟。是 [DefaultTolerationSeconds admission controller](https://git.k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds) 添加了这两个默认Toleration。 164 | 165 | 对于以下没有未设置`tolerationSeconds` 的Taint, [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) Pod是通过 `NoExecute` Toleration来创建的: 166 | 167 | - `node.alpha.kubernetes.io/unreachable` 168 | - `node.kubernetes.io/not-ready` 169 | 170 | 这确保了DaemonSet Pod对这些问题容忍而永远不会被驱逐,这与禁用此功能时的行为相匹配。 171 | 172 | 173 | 174 | 175 | 176 | ## Taint Nodes by Condition(使用Condition为Node添加Taint) 177 | 178 | 1.8版引入了一个Alpha功能,导致Node Controller创建与Node状态相对应的Taint。启用此功能时(可以通过在Scheduler的 `--feature-gates` 命令中添加 `TaintNodesByCondition=true` 来启用该功能,例如 `--feature-gates=FooBar=true,TaintNodesByCondition=true` ),Scheduler不会检查Node的Condition,而是检查Taint。这样可确保Node Condition不会影响调度到该Node上的内容。用户可通过添加适当的Pod Toleration来选择忽略Node的一些问题(在Node Condition中显示)。 179 | 180 | 为了确保打开此功能不会破坏DaemonSet的特性,从1.8版本开始,DaemonSet Controller会自动将以下 `NoSchedule` 的Toleration添加到所有daemon中: 181 | 182 | - `node.kubernetes.io/memory-pressure` 183 | - `node.kubernetes.io/disk-pressure` 184 | - `node.kubernetes.io/out-of-disk` (*only for critical pods*) 185 | 186 | 上述设置确保向后兼容性,但是我们了解,它们可能无法适应所有用户的需求,这就是为什么集群管理员可能需要向DaemonSet添加Arbitrary Toleration的原因。 187 | 188 | 189 | 190 | 191 | 192 | ## 原文 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /kubernetes/100-其他/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/100-其他/.DS_Store -------------------------------------------------------------------------------- /kubernetes/100-其他/Horizontal Pod Autoscaling.md: -------------------------------------------------------------------------------- 1 | # Horizontal Pod Autoscaling(HPA) 2 | 3 | 本文描述了Kubernetes中Horizontal Pod Autoscaling的当前状态。 4 | 5 | 6 | 7 | 8 | 9 | ## What is Horizontal Pod Autoscaling?(什么是HPA) 10 | 11 | 使用HPA,Kubernetes会根据观察到的CPU利用率(或根据在其他应用提供的度量标准,Beta状态)自动缩放Replication Controller、Deployment或ReplicaSet中的Pod个数。请注意,HPA不适用于无法缩放的对象,例如DaemonSet。 12 | 13 | Horizontal Pod Autoscaler实现为Kubernetes API资源和Controller。资源决定了Controller的行为。Controller定期调整Replication Controller或Deployment中的副本数,从而将观察到的平均CPU利用率与用户指定的目标相匹配。 14 | 15 | 16 | 17 | 18 | 19 | ## How does the Horizontal Pod Autoscaler work?(Horizontal Pod Autoscaler如何工作) 20 | 21 | ![1](images/hpa.png) 22 | 23 | Horizontal Pod Autoscaler被实现为一个控制回路,由Controller Manager的 `--horizontal-pod-autoscaler-sync-period` 标志(默认值为30秒)控制循环周期。 24 | 25 | 在每个周期内,Controller Manager根据每个HorizontalPodAutoscaler定义中指定的指标来查询资源利用。 Controller Manager从资源指标API(针对per-pod的资源指标)或自定义指标API(所有其他指标)中获取指标。 26 | 27 | - 对于per-pod的资源指标(如CPU),Controller从每个pod的资源指标API中获取指标,这些Pod是由HorizontalPodAutoscaler定位的。然后,如果设置了目标利用率值,则Controller计算利用率的值,跟每个pod中的容器上的资源请求的百分比相同。如果设置了目标原始值,则直接使用原始指标值。然后,Controller在所有目标pod中,获取利用率或原始值(取决于指定的目标类型)的平均值,并产生用于缩放期望的副本数量的比率。 28 | 29 | 请注意,如果某些pod的容器未设置相应的资源请求,则不会定义pod的CPU利用率,并且autoscaler不会对该指标采取任何操作。有关自动伸缩算法如何工作的更多信息,阅读 [autoscaling algorithm design document](https://git.k8s.io/community/contributors/design-proposals/autoscaling/horizontal-pod-autoscaler.md#autoscaling-algorithm) 。 30 | 31 | - 对于per-pod的自定义指标,Controller的功能类似于per-pod的资源指标,除了它适用于原始值而非利用率值。 32 | 33 | - 对于对象的指标,获取单个指标(描述所讨论的对象),并与目标值进行比较,从而产生如上所述的比率。 34 | 35 | HorizontalPodAutoscaler Controller可以两种不同的方式获取指标:直接使用Heapster访问与使用REST客户端访问。 36 | 37 | 当直接使用Heapster访问时,HorizontalPodAutoscaler直接通过API Server的service proxy subresource查询Heapster。 需在集群上部署Heapster并在kube-system这个namespace中运行。 38 | 39 | 有关使用REST客户端访问的详细信息,请参阅 [Support for custom metrics](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-custom-metrics) 。 40 | 41 | autoscaler通过 scale sub-resource访问相应的Replication Controller、Deployment或ReplicaSet。Scale是一个允许您动态设置副本数,并检查其当前状态的接口。有关scale sub-resource的更多细节可在 [here](https://git.k8s.io/community/contributors/design-proposals/autoscaling/horizontal-pod-autoscaler.md#scale-subresource) 找到。 42 | 43 | > 译者按:Heapster是一款容器集群监控及性能分析工具,拓展阅读: 44 | 45 | 46 | 47 | 48 | 49 | ## API Object 50 | 51 | Horizontal Pod Autoscaler是Kubernetes `autoscaling` API组中的API资源。当前稳定版本中,只包括对CPU自动缩放的支持,可在`autoscaling/v1` API版本中找到。 52 | 53 | Beta版本包括对内存以及自定义指标的支持,可以在`autoscaling/v2beta1` 找到。 在`autoscaling/v2beta1` 中引入的新字段,在使用`autoscaling/v1` 时被保留为注释。 54 | 55 | 有关API对象的更多详细信息,请参见 [HorizontalPodAutoscaler Object](https://git.k8s.io/community/contributors/design-proposals/autoscaling/horizontal-pod-autoscaler.md#horizontalpodautoscaler-object) 。 56 | 57 | 58 | 59 | 60 | 61 | ## Support for Horizontal Pod Autoscaler in kubectl(kubectl对Horizontal Pod Autoscaler的支持) 62 | 63 | 和所有API资源一样,Horizontal Pod Autoscaler以 `kubectl` 的标准方式支持。可使用`kubectl create` 命令创建一个新的autoscaler;通过`kubectl get hpa` 列出autoscaler;通过`kubectl describe hpa` 获得详细的描述;通过`kubectl delete hpa` 删除autoscaler。 64 | 65 | 此外,还有一个特殊的`kubectl autoscale` 命令,使用它可轻松创建一个Horizontal Pod Autoscaler。 例如,执行 `kubectl autoscale rc foo --min=2 --max=5 --cpu-percent=80` 将为*foo*这个Replication Controller创建一个autoscaler,目标CPU利用率设置为`80%` ,副本数量介于2和5之间。可在 [here](https://kubernetes.io/docs/user-guide/kubectl/v1.8/#autoscale) 找到 `kubectl autoscale` 的详细文档。 66 | 67 | 68 | 69 | 70 | 71 | ## Autoscaling during rolling update(滚动更新期间的自动缩放) 72 | 73 | 目前在Kubernetes中,可以通过直接管理Replication Controller或使用Deployment对象来执行 [rolling update](https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller/) ,当使用Deployment时,Deployment对象为您管理底层Replication Controller。Horizontal Pod Autoscaler仅支持后一种方法:Horizontal Pod Autoscaler被绑定到Deployment对象,它设置Deployment对象的大小,Deployment负责设置底层Replication Controller的大小。 74 | 75 | 当直接使用Replication Controller时,Horizontal Pod Autoscaler不能与滚动更新一起工作,即不能将Horizontal Pod Autoscaler绑定到Replication Controller并执行滚动更新(例如使用`kubectl rolling-update` )。 不行的原因是:当滚动更新创建一个新的Replication Controller时,Horizontal Pod Autoscaler将不会绑定到新的Replication Controller。 76 | 77 | 78 | 79 | 80 | 81 | ## Support for multiple metrics(对多个指标的支持) 82 | 83 | Kubernetes 1.6添加了对“基于多个指标缩放”的支持。 可使用`autoscaling/v2beta1` API版本,指定Horizontal Pod Autoscaler扩展的多个指标。 然后,Horizontal Pod Autoscaler Controller将对每个指标进行评估,并根据该指标提出新的规模。 最大建议的规模将被用作新的规模。 84 | 85 | 86 | 87 | 88 | 89 | ## 对自定义指标的支持 90 | 91 | **注意** :Kubernetes 1.2根据使用特殊Annotation的application-specific metrics(特定于应用程序的指标),增加了对缩放的Alpha支持。在Kubernetes 1.6中删除了对这些Annotation的支持,而是使用新的自动缩放API。虽然,用于收集自定义指标的旧方法仍然可用,但是这些指标将不可被Horizontal Pod Autoscaler使用,并且,用于指定要缩放的自定义指标的Annotation,不再由Horizontal Pod Autoscaler Controller执行。 92 | 93 | Kubernetes 1.6增加了在Horizontal Pod Autoscaler中使用自定义指标的支持。 您可在`autoscaling/v2beta1` API中,添加Horizontal Pod Autoscaler要使用的自定义指标。这样,Kubernetes就会查询新的自定义指标API来获取适当的自定义指标的值。 94 | 95 | 96 | 97 | ### Requirements(需要的条件) 98 | 99 | 要使用Horizontal Pod Autoscaler的自定义指标,您必须在部署集群时设置必要的配置: 100 | 101 | - [Enable the API aggregation layer](https://kubernetes.io/docs/tasks/access-kubernetes-api/configure-aggregation-layer/) (启用API聚合层) 102 | 103 | - 使用API aggregation layer注册资源指标API和自定义指标API。 这两个API server必须*在*您的集群上运行。 104 | 105 | - *资源指标API* :可使用Heapster的资源指标API实现,方法是运行Heapster时将其`--api-server` 标志设为true。 106 | - *自定义指标API* :这必须由单独的组件提供。 样板代码,请参阅 [kubernetes-incubator/custom-metrics-apiserver](https://github.com/kubernetes-incubator/custom-metrics-apiserver) 以及 [k8s.io/metrics](https://github.com/kubernetes/metrics) 。 107 | 108 | - 为kube-controller-manager设置相应的标志: 109 | 110 | - `--horizontal-pod-autoscaler-use-rest-clients` 应设为true。 111 | 112 | - `--kubeconfig ` 或 `--master ` 113 | 114 | 请注意,可使用`--master` 或`--kubeconfig` 标志; `--master` 将会覆盖`--kubeconfig` ,如果两者都被指定。这些标志指定API aggregation layer的位置,允许Controller Manager与 API server通信。 115 | 116 | 在Kubernetes 1.7中,Kubernetes提供的标准聚合层与kube-apiserver一起运行,因此可使用 `kubectl get pods --selector k8s-app=kube-apiserver --namespace kube-system -o jsonpath='{.items[0].status.podIP}'`找到目标IP。 117 | 118 | 119 | 120 | 121 | 122 | ## Further reading(进一步阅读) 123 | 124 | - 设计文档: [Horizontal Pod Autoscaling](https://git.k8s.io/community/contributors/design-proposals/autoscaling/horizontal-pod-autoscaler.md). 125 | - kubectl autoscale 命令: [kubectl autoscale](https://kubernetes.io/docs/user-guide/kubectl/v1.8/#autoscale). 126 | - 使用示例: [Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/). 127 | 128 | 129 | 130 | 131 | 132 | ## 原文 133 | 134 | -------------------------------------------------------------------------------- /kubernetes/100-其他/K8s资源分配.md: -------------------------------------------------------------------------------- 1 | # K8s资源分配 2 | 3 | ## 准备工作 4 | 5 | 本节中的示例需要安装Heapster。因此,需要先安装Heapster,对于Minikube,执行如下操作即可。 6 | 7 | ```shell 8 | minikube addons enable heapster 9 | ``` 10 | 11 | 查看Heapster Service是否已在运行: 12 | 13 | ``` 14 | kubectl get services --namespace=kube-system 15 | ``` 16 | 17 | 18 | 19 | ### TIPS 20 | 21 | 按理,对于Minikube,启用Heapster addon后,即可在Dashboard上看到各种资源的CPU占用等指标。然而,对于`minikube 0.22.x` ,在Dashboard上无法看到,可使用如下命令,直接查询Grafana监控界面: 22 | 23 | ```shell 24 | minikube addons open heapster 25 | ``` 26 | 27 | 相关Issue: 28 | 29 | 30 | 31 | 32 | 33 | ## 限制CPU分配 34 | 35 | ### 示例 36 | 37 | * `cpu-request-limit.yaml` : 38 | 39 | ```yaml 40 | apiVersion: v1 41 | kind: Pod 42 | metadata: 43 | name: cpu-demo 44 | spec: 45 | containers: 46 | - name: cpu-demo-ctr 47 | image: vish/stress 48 | resources: 49 | # 最多使用1个CPU单位 50 | limits: 51 | cpu: "1" 52 | # 至少保证0.5个CPU单位 53 | requests: 54 | cpu: "0.5" 55 | # 容器启动时的参数 56 | args: 57 | # 使用2个CPU单位 58 | - -cpus 59 | - "2" 60 | ``` 61 | 62 | * 创建Pod: 63 | 64 | ```shell 65 | kubectl create -f cpu-request-limit.yaml 66 | ``` 67 | 68 | * 查看Pod状态: 69 | 70 | ```shell 71 | kubectl get pod cpu-demo -o yaml 72 | ``` 73 | 74 | * 启动`proxy` ,并查询配额信息: 75 | 76 | ```shell 77 | kubectl proxy 78 | # 另起一个终端,输入: 79 | curl http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/default/pods/cpu-demo/metrics/cpu/usage_rate 80 | ``` 81 | 82 | 即可看到监控信息。 83 | 84 | 85 | 在本例中,尽管容器启动时,尝试使用2个CPU单位,但由于配置了只允许使用1个CPU单位,因此,最终最多只能使用1个CPU单位。 86 | 87 | 88 | 89 | ### CPU单位 90 | 91 | CPU资源以*cpu为*单位。 在Kubernetes,一个cpu相当于: 92 | 93 | - 1 AWS vCPU 94 | - 1个GCP核心 95 | - 1 Azure vCore 96 | - 1个在裸机Intel处理器上的超线程 97 | 98 | 允许小数值。你可以使用m后缀来表示“毫”。例如100m cpu,100millicpu和0.1cpu表达的含义其实是相同的。精度不允许超过1m。 99 | 100 | > 精度不允许超过1m的意思是,你不能指定有500.88m个CPU单位,精度最小是毫,就像人民币中最小的单位是分一样。 101 | 102 | CPU配额是一个绝对值,而非相对值;“0.1 CPU”在单核、双核或48核机器表示的配额是相同的。 103 | 104 | 105 | 106 | ### 配额超过任何Node的容量 107 | 108 | CPU最低要求和最大限制与容器相关联,但将Pod视为具有CPU最小配合和最大限制是有用的。Pod的CPU最小配需求是Pod中所有容器的CPU请求的总和。同样,Pod的CPU最大限制是Pod中所有容器的CPU最大限制的总和。 109 | 110 | Pod的调度是基于最低要求的。只有当Node具有足够可用的CPU资源时,Pod才会在Node上运行。 111 | 112 | 在本练习中,您将创建一个非常大的CPU最低要求,以至于它超出了集群中任何Node的容量。以下是具有一个容器的Pod的配置文件。容器请求100 cpu,这可能超过集群中任何Node的容量。 113 | 114 | ```yaml 115 | apiVersion: v1 116 | kind: Pod 117 | metadata: 118 | name: cpu-demo-2 119 | spec: 120 | containers: 121 | - name: cpu-demo-ctr-2 122 | image: vish/stress 123 | resources: 124 | limits: 125 | cpu: "100" 126 | requests: 127 | cpu: "100" 128 | args: 129 | - -cpus 130 | - "2" 131 | ``` 132 | 133 | 创建该Pod后,使用`kubectl get pod cpu-demo-2` 查看Pod状态,即可看到类似如下的结果。由输出可知,Pod的状态为Pending。也就是说,Pod并没有被调度到任何Node上运行,它将无限期地保持在Pending状态。 134 | 135 | ``` 136 | kubectl get pod cpu-demo-2 137 | NAME READY STATUS RESTARTS AGE 138 | cpu-demo-2 0/1 Pending 0 7m 139 | ``` 140 | 141 | 使用`kubectl describe pod cpu-demo-2` 命令查看Pod详情,即可看到类似如下的结果。由输出可看到无法调度的具体原因。 142 | 143 | ``` 144 | Events: 145 | Reason Message 146 | ------ ------- 147 | FailedScheduling No nodes are available that match all of the following predicates:: Insufficient cpu (3). 148 | ``` 149 | 150 | 151 | 152 | 153 | 154 | ## 限制内存分配 155 | 156 | ### 示例 157 | 158 | * `memory-request-limit.yaml` 159 | 160 | ```yaml 161 | apiVersion: v1 162 | kind: Pod 163 | metadata: 164 | name: memory-demo 165 | spec: 166 | containers: 167 | - name: memory-demo-ctr 168 | image: vish/stress 169 | resources: 170 | # 最大允许使用200Mi内存 171 | limits: 172 | memory: "200Mi" 173 | # 至少保证200Mi的内存资源 174 | requests: 175 | memory: "100Mi" 176 | args: 177 | # 尝试分配150Mi内存给容器 178 | - -mem-total 179 | - 150Mi 180 | - -mem-alloc-size 181 | - 10Mi 182 | - -mem-alloc-sleep 183 | - 1s 184 | ``` 185 | 186 | * 查看Pod状态: 187 | 188 | ```shell 189 | kubectl get pod memory-demo -o yaml 190 | ``` 191 | 192 | 可看到类似如下结果: 193 | 194 | ``` 195 | ... 196 | resources: 197 | limits: 198 | memory: 200Mi 199 | requests: 200 | memory: 100Mi 201 | ... 202 | ``` 203 | 204 | * 启动`proxy` 并查询配额信息: 205 | 206 | ``` 207 | kubectl proxy 208 | curl http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/default/pods/memory-demo/metrics/memory/usage 209 | ``` 210 | 211 | 可看到如下结果: 212 | 213 | ``` 214 | { 215 | "timestamp": "2017-06-20T18:54:00Z", 216 | "value": 162856960 217 | } 218 | ``` 219 | 220 | 由结果可知,Pod正使用大约162,900,000的内存,大约为150 MiB。这比Pod的100 MiB要求大,但在Pod的200MiB限制之内。 221 | 222 | 223 | 224 | 225 | ### 超出容器的内存限制 226 | 227 | 示例: 228 | 229 | ```yaml 230 | apiVersion: v1 231 | kind: Pod 232 | metadata: 233 | name: memory-demo-2 234 | spec: 235 | containers: 236 | - name: memory-demo-2-ctr 237 | image: vish/stress 238 | resources: 239 | requests: 240 | memory: 50Mi 241 | limits: 242 | memory: "100Mi" 243 | args: 244 | - -mem-total 245 | - 250Mi 246 | - -mem-alloc-size 247 | - 10Mi 248 | - -mem-alloc-sleep 249 | - 1s 250 | ``` 251 | 252 | 此时,容器将不能运行。Container会因为内存不足(OOM)而被杀死。 253 | 254 | 类似的,如果指定Pod的内存超过K8s集群中任何Node的内存,Pod也无法运行。 255 | 256 | 257 | 258 | ### 内存单位 259 | 260 | 内存资源以字节为单位。使用一个整数或一个定点整数跟上以下后缀,来描述内存:E,P,T,G,M,K,Ei,Pi,Ti,Gi,Mi,Ki。 例如,以下代表大致相同的值: 261 | 262 | ``` 263 | 128974848, 129e6, 129M , 123Mi 264 | ``` 265 | 266 | 267 | 268 | 269 | 270 | ## 参考文档 271 | 272 | * 官方文档:《Assign CPU Resources to Containers and Pods》: 273 | * 官方文档:《Assign Memory Resources to Containers and Pods》: 274 | * k8s的资源分配: 275 | 276 | 277 | 278 | 279 | 280 | -------------------------------------------------------------------------------- /kubernetes/100-其他/images/hpa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/100-其他/images/hpa.png -------------------------------------------------------------------------------- /kubernetes/100-其他/images/k8s-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/100-其他/images/k8s-architecture.png -------------------------------------------------------------------------------- /kubernetes/100-其他/images/kubernetes-install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/100-其他/images/kubernetes-install.png -------------------------------------------------------------------------------- /kubernetes/100-其他/images/service-pod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/100-其他/images/service-pod.png -------------------------------------------------------------------------------- /kubernetes/100-其他/实战:使用K8s编排Wordpress博客.md: -------------------------------------------------------------------------------- 1 | # 标题 2 | 3 | ## MySQL 4 | 5 | ### 创建deployment 6 | 7 | ```yaml 8 | apiVersion: extensions/v1beta1 9 | kind: Deployment # 定义一个deployment 10 | metadata: 11 | name: mysql # deployment名称,全局唯一 12 | labels: 13 | app: mysql123 14 | release: stable 15 | spec: 16 | replicas: 1 17 | selector: 18 | matchLabels: 19 | app: mysql123 # deployment的POD标签选择器,即:监控和管理拥有这些标签的POD实例,确保当前集群中有且只有replicas个POD实例在运行 20 | template: 21 | metadata: 22 | labels: # 指定该POD的标签 23 | app: mysql123 # POD副本拥有的标签,需要与deployment的selector一致 24 | spec: 25 | containers: 26 | - name: mysql 27 | image: mysql 28 | ports: 29 | - containerPort: 3306 30 | env: 31 | - name: MYSQL_ROOT_PASSWORD 32 | value: "123456" 33 | ``` 34 | 35 | ### 创建SVC 36 | 37 | ```yaml 38 | apiVersion: v1 39 | kind: Service 40 | metadata: 41 | name: mysql # Service名称,全局唯一 42 | labels: 43 | app: mysql123 44 | spec: 45 | ports: 46 | - port: 3306 # Service提供服务的端口号 47 | selector: 48 | app: mysql123 # 选择器 49 | ``` 50 | 51 | ## Wordpress 52 | 53 | ### 创建deployment 54 | 55 | ```yaml 56 | apiVersion: extensions/v1beta1 57 | kind: Deployment 58 | metadata: 59 | name: wordpress 60 | labels: 61 | app: wordpress 62 | spec: 63 | replicas: 1 64 | selector: 65 | matchLabels: 66 | app: wordpress 67 | template: 68 | metadata: 69 | labels: 70 | app: wordpress 71 | spec: 72 | containers: 73 | - name: wordpress 74 | image: wordpress:4.8-apache 75 | ports: 76 | - containerPort: 80 77 | env: 78 | - name: WORDPRESS_DB_HOST 79 | value: "mysql" 80 | - name: WORDPRESS_DB_PASSWORD 81 | value: "123456" 82 | ``` 83 | 84 | ### 创建SVC 85 | 86 | ```yaml 87 | apiVersion: v1 88 | kind: Service 89 | metadata: 90 | name: wordpress 91 | labels: 92 | app: wordpress 93 | spec: 94 | type: NodePort # 为该Service开启NodePort方式的外网访问模式 95 | ports: 96 | - port: 80 # Service提供服务的端口号 97 | targetPort: 80 # 将Service的80端口转发到Pod中容器的80端口上 98 | nodePort: 32001 # 在k8s集群外访问的端口,如果设置了NodePort类型,但没设置nodePort,将会随机映射一个端口,可使用kubectl get svc wordpress看到 99 | selector: 100 | app: wordpress 101 | ``` 102 | 103 | 104 | 105 | ## 删除 106 | 107 | ```shell 108 | kubectl delete deployment,svc -l app=mysql123 109 | kubectl delete deployment,svc -l app=wordpress 110 | ``` 111 | 112 | 113 | -------------------------------------------------------------------------------- /kubernetes/99-安装/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/99-安装/.DS_Store -------------------------------------------------------------------------------- /kubernetes/99-安装/01-安装单机版Kubernetes.md: -------------------------------------------------------------------------------- 1 | # 安装Kubernetes(单机) 2 | 3 | ## 对于Mac/Windows 10 4 | 5 | * 前提:保持网络畅通 6 | * 系统版本满足要求 7 | 8 | 对于macOS或者Windows 10,Docker已经原生支持了Kubernetes。你所要做的只是启用Kubernetes即可,如下图: 9 | 10 | ![](images/kubernetes-install.png) 11 | 12 | 如果因为网络问题安装不成功,可参考 的说明进行安装。 13 | 14 | **TIPS**: 15 | 16 | 在Mac上: 17 | 18 | 如果在Kubernetes部署的过程中出现问题,可以通过docker desktop应用日志获得实时日志信息: 19 | 20 | ``` 21 | pred='process matches ".*(ocker|vpnkit).*" 22 | || (process in {"taskgated-helper", "launchservicesd", "kernel"} && eventMessage contains[c] "docker")' 23 | /usr/bin/log stream --style syslog --level=debug --color=always --predicate "$pred" 24 | ``` 25 | 26 | 在Windows上: 27 | 28 | 如果在Kubernetes部署的过程中出现问题,可以在 C:\ProgramData\DockerDesktop下的service.txt 查看Docker日志; 如果看到 Kubernetes一直在启动状态,请参考 [Issue 3769(comment)](https://github.com/docker/for-win/issues/3769#issuecomment-486046718) 和 [Issue 1962(comment)](https://github.com/docker/for-win/issues/1962#issuecomment-431091114) 29 | 30 | ## Minikube 31 | 32 | 一些场景下,安装Minikube是个不错的选择。该方式适用于Windows 10、Linux、macOS 33 | 34 | * 官方安装说明文档: 35 | * 如何在Windows 10上运行Docker和Kubernetes?: 36 | 37 | 38 | 39 | ## 启用Kubernetes Dashboard 40 | 41 | 执行: 42 | 43 | ``` 44 | kubectl proxy 45 | ``` 46 | 47 | 访问: 48 | 49 | 50 | 51 | 参考: 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /kubernetes/99-安装/02-使用Kubespray部署生产可用的Kubernetes集群(1.11.2).md: -------------------------------------------------------------------------------- 1 | # 使用Kubespray部署生产可用的Kubernetes集群(1.11.2) 2 | 3 | **前提**:科学上网,或自行将gcr.io的镜像转成其他镜像仓库的镜像。 4 | 5 | 6 | 7 | Kubernetes的安装部署是难中之难,每个版本安装方式都略有区别。笔者一直想找一种`支持多平台`、`相对简单` 、`适用于生产环境` 的部署方案。经过一段时间的调研,有如下几种解决方案进入笔者视野: 8 | 9 | | 部署方案 | 优点 | 缺点 | 10 | | ------------------------------------------------------------ | ------------------------------------------------------ | ---------------------- | 11 | | [Kubeadm](https://github.com/kubernetes/kubeadm) | 官方出品 | 部署较麻烦、不够透明 | 12 | | [Kubespray](https://github.com/kubernetes-incubator/kubespray) | 官方出品、部署较简单、懂Ansible就能上手 | 不够透明 | 13 | | [RKE](https://github.com/rancher/rke) | 部署较简单、需要花一些时间了解RKE的cluster.yml配置文件 | 不够透明 | 14 | | 手动部署 [第三方操作文档](https://github.com/opsnull/follow-me-install-kubernetes-cluster) | 完全透明、可配置、便于理解K8s各组件之间的关系 | 部署非常麻烦,容易出错 | 15 | 16 | 其他诸如Kops之类的方案,由于无法跨平台,或者其他因素,被我pass了。 17 | 18 | 最终,笔者决定使用Kubespray部署Kubernetes集群。**也希望大家能够一起讨论,总结出更加好的部署方案**。 19 | 20 | 废话不多说,以下是操作步骤。 21 | 22 | 23 | 24 | 25 | 26 | > 注:撰写本文时,笔者临时租赁了几台海外阿里云机器,实现了科学上网。如果您的机器在国内,请: 27 | > 28 | > - 考虑科学上网 29 | > - 或修改Kubespray中的gcr地址,改为其他仓库地址,例如阿里云镜像地址。 30 | 31 | ## 主机规划 32 | 33 | | IP | 作用 | 34 | | ----------- | -------------- | 35 | | 172.20.0.87 | ansible-client | 36 | | 172.20.0.88 | master,node | 37 | | 172.20.0.89 | master,node | 38 | | 172.20.0.90 | node | 39 | | 172.20.0.91 | node | 40 | | 172.20.0.92 | node | 41 | 42 | ## 准备工作 43 | 44 | ### 关闭selinux 45 | 46 | 所有机器都必须关闭selinux,执行如下命令即可。 47 | 48 | ``` 49 | ~]# setenforce 0 50 | ~]# sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux 51 | ``` 52 | 53 | ### 网络配置 54 | 55 | #### 在master机器上 56 | 57 | ``` 58 | ~]# firewall-cmd --permanent --add-port=6443/tcp 59 | ~]# firewall-cmd --permanent --add-port=2379-2380/tcp 60 | ~]# firewall-cmd --permanent --add-port=10250/tcp 61 | ~]# firewall-cmd --permanent --add-port=10251/tcp 62 | ~]# firewall-cmd --permanent --add-port=10252/tcp 63 | ~]# firewall-cmd --permanent --add-port=10255/tcp 64 | ~]# firewall-cmd --reload 65 | ~]# modprobe br_netfilter 66 | ~]# echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables 67 | ~]# sysctl -w net.ipv4.ip_forward=1 68 | ``` 69 | 70 | 如果关闭了防火墙,则只需执行最下面三行。 71 | 72 | #### 在node机器上 73 | 74 | ``` 75 | ~]# firewall-cmd --permanent --add-port=10250/tcp 76 | ~]# firewall-cmd --permanent --add-port=10255/tcp 77 | ~]# firewall-cmd --permanent --add-port=30000-32767/tcp 78 | ~]# firewall-cmd --permanent --add-port=6783/tcp 79 | ~]# firewall-cmd --reload 80 | ~]# echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables 81 | ~]# sysctl -w net.ipv4.ip_forward=1 82 | ``` 83 | 84 | 如果关闭了防火墙,则只需执行最下面两行。 85 | 86 | #### 【可选】关闭防火墙 87 | 88 | ``` 89 | systemctl stop firewalld 90 | ``` 91 | 92 | ## 在ansible-client机器上安装ansible 93 | 94 | ### 安装ansible 95 | 96 | ``` 97 | ~]# sudo yum install epel-release 98 | ~]# sudo yum install ansible 99 | ``` 100 | 101 | ### 安装jinja2 102 | 103 | ``` 104 | ~]# easy_install pip 105 | ~]# pip2 install jinja2 --upgrade 106 | ``` 107 | 108 | 如果执行`pip2 install jinja2 --upgrade` 出现类似如下的提示: 109 | 110 | ``` 111 | You are using pip version 9.0.1, however version 18.0 is available. 112 | You should consider upgrading via the 'pip install --upgrade pip' command. 113 | ``` 114 | 115 | 则执行`pip install --upgrade pip` 升级pip,再执行`pip2 install jinja2 --upgrade` 116 | 117 | ### 安装Python 3.6 118 | 119 | ``` 120 | ~]# sudo yum install python36 –y 121 | ``` 122 | 123 | ## 在ansible-client机器上配置免密登录 124 | 125 | ### 生成ssh公钥和私钥 126 | 127 | 在ansible-cilent机器上执行: 128 | 129 | ``` 130 | ~]# ssh-keygen 131 | ``` 132 | 133 | 然后三次回车,生成ssh公钥和私钥。 134 | 135 | ### 建立ssh单向通道 136 | 137 | 在ansible-cilent机器上执行: 138 | 139 | ``` 140 | ~]# ssh-copy-id root@172.20.0.88 #将公钥分发给88机器 141 | ~]# ssh-copy-id root@172.20.0.89 142 | ~]# ssh-copy-id root@172.20.0.90 143 | ~]# ssh-copy-id root@172.20.0.91 144 | ~]# ssh-copy-id root@172.20.0.92 145 | ``` 146 | 147 | ## 在ansible-client机器上安装kubespray 148 | 149 | - 下载kubespray 150 | 151 | > **TIPS**:本文下载的是master分支,如果大家要部署到线上环境,建议下载RELEASE分支。笔者撰写本文时,最新的RELEASE是2.6.0,RELEASE版本下载地址:) 152 | 153 | ``` 154 | ~]# git clone https://github.com/kubernetes-incubator/kubespray.git 155 | ``` 156 | 157 | - 安装kubespray需要的包: 158 | 159 | ``` 160 | ~]# cd kubespray 161 | ~]# sudo pip install -r requirements.txt 162 | ``` 163 | 164 | - 拷贝`inventory/sample` ,命名为`inventory/mycluster` ,mycluster可以改为其他你喜欢的名字 165 | 166 | ``` 167 | cp -r inventory/sample inventory/mycluster 168 | ``` 169 | 170 | - 使用inventory_builder,初始化inventory文件 171 | 172 | ``` 173 | ~]# declare -a IPS=(172.20.0.88 172.20.0.89 172.20.0.90 172.20.0.91 172.20.0.92) 174 | ~]# CONFIG_FILE=inventory/mycluster/hosts.ini python36 contrib/inventory_builder/inventory.py ${IPS[@]} 175 | ``` 176 | 177 | 此时,会看到`inventory/mycluster/host.ini` 文件内容类似如下: 178 | 179 | ``` 180 | [k8s-cluster:children] 181 | kube-master 182 | kube-node 183 | 184 | [all] 185 | node1 ansible_host=172.20.0.88 ip=172.20.0.88 186 | node2 ansible_host=172.20.0.89 ip=172.20.0.89 187 | node3 ansible_host=172.20.0.90 ip=172.20.0.90 188 | node4 ansible_host=172.20.0.91 ip=172.20.0.91 189 | node5 ansible_host=172.20.0.92 ip=172.20.0.92 190 | 191 | [kube-master] 192 | node1 193 | node2 194 | 195 | [kube-node] 196 | node1 197 | node2 198 | node3 199 | node4 200 | node5 201 | 202 | [etcd] 203 | node1 204 | node2 205 | node3 206 | 207 | [calico-rr] 208 | 209 | [vault] 210 | node1 211 | node2 212 | node3 213 | ``` 214 | 215 | - 使用ansible playbook部署kubespray 216 | 217 | ``` 218 | ~]# ansible-playbook -i inventory/mycluster/hosts.ini cluster.yml 219 | ``` 220 | 221 | - 大概20分钟左右,Kubernetes即可安装完毕。 222 | 223 | ## 验证 224 | 225 | 验证1:查看Node状态 226 | 227 | ``` 228 | ]# kubectl get nodes 229 | NAME STATUS ROLES AGE VERSION 230 | node1 Ready master,node 2m v1.11.2 231 | node2 Ready master,node 2m v1.11.2 232 | node3 Ready node 2m v1.11.2 233 | node4 Ready node 2m v1.11.2 234 | node5 Ready node 2m v1.11.2 235 | ``` 236 | 237 | 每个node都是ready的,说明OK。 238 | 239 | 验证2:部署一个NGINX 240 | 241 | ``` 242 | # 启动一个单节点nginx 243 | ]# kubectl run nginx --image=nginx:1.7.9 --port=80 244 | 245 | # 为“nginx”服务暴露端口 246 | ]# kubectl expose deployment nginx --type=NodePort 247 | 248 | # 查看nginx服务详情 249 | ]# kubectl get svc nginx 250 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 251 | nginx NodePort 10.233.29.96 80:32345/TCP 14s 252 | 253 | # 访问测试,如果能够正常返回NGINX首页,说明正常 254 | ]# curl localhost:32345 255 | ``` 256 | 257 | ## 卸载 258 | 259 | ``` 260 | ]# ansible-playbook -i inventory/mycluster/hosts.ini reset.yml 261 | ``` 262 | 263 | ## 遇到的问题 264 | 265 | Calico网络插件部署失效。这是Calico 3.2所带来的问题,原因详见: 266 | 267 | 解决方法:,即:将Calico降级到3.1.3。 268 | 269 | ## 参考文档: 270 | 271 | - Kubespray – 10 Simple Steps for Installing a Production-Ready, Multi-Master HA Kubernetes Cluster: 272 | 273 | > **TIPS**:主要的参考文档,里面还讲解了Kubespray的一些配置,与可能会遇到的问题及解决方案。 274 | 275 | - 使用Kubespray 部署kubernetes 高可用集群: 276 | 277 | - kubespray(ansible)自动化安装k8s集群: 278 | 279 | > **TIPS**:里面有将如何替换gcr镜像为国内镜像 280 | 281 | - Installing Kubernetes On-premises/Cloud Providers with Kubespray: -------------------------------------------------------------------------------- /kubernetes/99-安装/images/kubernetes-install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itmuch/docker-book/eb200a552b1d1284f5be47bd28bb1bee3d31df2f/kubernetes/99-安装/images/kubernetes-install.png -------------------------------------------------------------------------------- /kubernetes/README.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | 3 | Kubernetes开源书。不啰嗦了,JUST READ IT. 4 | 5 | - GitHub地址: 6 | - Gitee地址: 7 | 8 | 欢迎star、fork,一起讨论! 9 | 10 | QQ群:731548893 11 | 12 | 微信群:加jumping_me,注明加群。 -------------------------------------------------------------------------------- /kubernetes/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Introduction](README.md) 4 | * [01-什么是Kubernetes](01-Overview/什么是K8s.md) 5 | * [02-安装单机版Kubernetes](99-安装/01-安装单机版Kubernetes.md) 6 | * [03-使用Kubespray部署生产可用的Kubernetes集群(1.11.2)](99-安装/02-使用Kubespray部署生产可用的Kubernetes集群(1.11.2).md) 7 | * [04-K8s组件](01-Overview/K8s组件.md) 8 | * [05-Kubernetes API](01-Overview/Kubernetes API.md) 9 | * [06-理解K8s对象](01-Overview/Working with Kubernetes Objects/理解K8s对象.md) 10 | * [07-Name](01-Overview/Working with Kubernetes Objects/Name.md) 11 | * [08-Namespace](01-Overview/Working with Kubernetes Objects/Namespace.md) 12 | * [09-Label和Selector](01-Overview/Working with Kubernetes Objects/Label和Selector.md) 13 | * [10-Annotation](01-Overview/Working with Kubernetes Objects/Annotation.md) 14 | * [11-K8s架构及基本概念](02-Kubernetes Architecture/K8s架构及基本概念.md) 15 | * [12-Master与Node的通信](02-Kubernetes Architecture/Master与Node的通信.md) 16 | * [13-Node](02-Kubernetes Architecture/Node.md) 17 | * [14-Pod](05-Workloads/Pods/Pod.md) 18 | * [15-Replica Set](05-Workloads/Controllers/Replica Set.md) 19 | * [16-Deployment](05-Workloads/Controllers/Deployment.md) 20 | * [17-StatefulSet](05-Workloads/Controllers/StatefulSet.md) 21 | * [18-Daemon Set](05-Workloads/Controllers/Daemon Set.md) 22 | * [19-配置最佳实践](06-Configuration/Configuration Best Practices.md) 23 | * [20-管理容器的计算资源](06-Configuration/Managing Compute Resources for Containers.md) 24 | * [21-Kubernetes资源分配](100-其他/K8s资源分配.md) 25 | * [22-将Pod分配到Node](06-Configuration/Assigning Pods to Nodes.md) 26 | * [23-容忍与污点](06-Configuration/Taints and Tolerations.md) 27 | * [24-Secret](06-Configuration/Secrets.md) 28 | * [25-Pod优先级和抢占](06-Configuration/Pod Priority and Preemption.md) 29 | * [26-Service](07-Services, Load Balancing, and Networking/Service.md) 30 | * [27-Ingress Resources](07-Services, Load Balancing, and Networking/Ingress Resources.md) 31 | * [28-动态水平扩容](100-其他/Horizontal Pod Autoscaling.md) 32 | * [29-实战:使用K8s编排Wordpress博客](100-其他/实战:使用K8s编排Wordpress博客.md) 33 | -------------------------------------------------------------------------------- /kubernetes/book.json: -------------------------------------------------------------------------------- 1 | { 2 | "title" : "Kubernetes实战", 3 | "author" : "www.itmuch.com", 4 | "links" : { 5 | "sidebar" : { 6 | "Home" : "http://www.itmuch.com" 7 | } 8 | } 9 | } --------------------------------------------------------------------------------