├── .github
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── OWNERS
├── README.md
└── tutorials
├── images
├── deployment_initial.png
├── deployment_scale.png
├── deployment_service.png
├── deployment_update_1.png
├── deployment_update_2.png
├── deployment_update_done.png
├── deployment_update_initial.png
├── hpa.png
├── kubernetes_cluster.png
└── labels.png
├── lab1-installation.md
├── lab2-application-and-service.md
├── lab3-manual-installtion.md
├── lab4-concepts.md
└── resources
├── class.yaml
├── coredns.yaml
├── cronjob.yaml
├── daemonset.yaml
├── debian.yaml
├── debian_never_restart.yaml
├── deployment_nginx.yaml
├── deployment_php_cache.yaml
├── emptydir_pod.yaml
├── game.properties
├── job.yaml
├── kube-flannel.yaml
├── ns.yaml
├── pod.yaml
├── pod_configmap.yaml
├── pod_exceeds_quota.yaml
├── pod_health.yaml
├── pod_unhealth.yaml
├── pod_with_pvc.yaml
├── pv_hostpath.yaml
├── pvc.yaml
├── pvc_standard.yaml
├── quota.yaml
└── ui.properties
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | **Is this a BUG REPORT or FEATURE REQUEST?**:
4 |
5 | > Uncomment only one, leave it on its own line:
6 | >
7 | > /kind bug
8 | > /kind feature
9 |
10 | **What happened**:
11 |
12 | **What you expected to happen**:
13 |
14 | **How to reproduce it (as minimally and precisely as possible)**:
15 |
16 | **Anything else we need to know?**:
17 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | **What this PR does / why we need it**:
4 |
5 | Add your description
6 |
7 | **Which issue(s) this PR is related to** *(optional, link to 3rd issue(s))*:
8 |
9 | Fixes #
10 |
11 | Reference to #
12 |
13 |
14 | **Special notes for your reviewer**:
15 |
16 | /cc @your-reviewer
17 |
18 |
26 |
27 | **Release note**:
28 |
32 |
33 | ```release-note
34 | NONE
35 | ```
36 |
37 |
47 |
--------------------------------------------------------------------------------
/OWNERS:
--------------------------------------------------------------------------------
1 | approvers:
2 | - ddysher
3 | - bbbmj
4 | reviewers:
5 | - ddysher
6 | - bbbmj
7 | - gaocegege
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
4 |
5 | - [Kubernetes 学习路径](#kubernetes-%E5%AD%A6%E4%B9%A0%E8%B7%AF%E5%BE%84)
6 | - [背景](#%E8%83%8C%E6%99%AF)
7 | - [学习路径](#%E5%AD%A6%E4%B9%A0%E8%B7%AF%E5%BE%84)
8 | - [第一阶段 炼气期(2-4 周,每周 3-5 小时)](#%E7%AC%AC%E4%B8%80%E9%98%B6%E6%AE%B5-%E7%82%BC%E6%B0%94%E6%9C%9F2-4-%E5%91%A8%E6%AF%8F%E5%91%A8-3-5-%E5%B0%8F%E6%97%B6)
9 | - [目标](#%E7%9B%AE%E6%A0%87)
10 | - [路径](#%E8%B7%AF%E5%BE%84)
11 | - [心法](#%E5%BF%83%E6%B3%95)
12 | - [第二阶段 筑基期(4-6 周,每周 8-10 小时)](#%E7%AC%AC%E4%BA%8C%E9%98%B6%E6%AE%B5-%E7%AD%91%E5%9F%BA%E6%9C%9F4-6-%E5%91%A8%E6%AF%8F%E5%91%A8-8-10-%E5%B0%8F%E6%97%B6)
13 | - [目标](#%E7%9B%AE%E6%A0%87-1)
14 | - [路径](#%E8%B7%AF%E5%BE%84-1)
15 | - [心法](#%E5%BF%83%E6%B3%95-1)
16 | - [第三阶段 金丹期(2-4 周,每周 3-5 小时)](#%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5-%E9%87%91%E4%B8%B9%E6%9C%9F2-4-%E5%91%A8%E6%AF%8F%E5%91%A8-3-5-%E5%B0%8F%E6%97%B6)
17 | - [目标](#%E7%9B%AE%E6%A0%87-2)
18 | - [路径](#%E8%B7%AF%E5%BE%84-2)
19 | - [心法](#%E5%BF%83%E6%B3%95-2)
20 | - [第四阶段 元婴期(4-6 周,每周 8-10 小时)](#%E7%AC%AC%E5%9B%9B%E9%98%B6%E6%AE%B5-%E5%85%83%E5%A9%B4%E6%9C%9F4-6-%E5%91%A8%E6%AF%8F%E5%91%A8-8-10-%E5%B0%8F%E6%97%B6)
21 | - [目标](#%E7%9B%AE%E6%A0%87-3)
22 | - [路径](#%E8%B7%AF%E5%BE%84-3)
23 | - [心法](#%E5%BF%83%E6%B3%95-3)
24 | - [第五阶段 化神期(3-5 周,每周 6-8 小时)](#%E7%AC%AC%E4%BA%94%E9%98%B6%E6%AE%B5-%E5%8C%96%E7%A5%9E%E6%9C%9F3-5-%E5%91%A8%E6%AF%8F%E5%91%A8-6-8-%E5%B0%8F%E6%97%B6)
25 | - [目标](#%E7%9B%AE%E6%A0%87-4)
26 | - [路径](#%E8%B7%AF%E5%BE%84-4)
27 | - [心法](#%E5%BF%83%E6%B3%95-4)
28 | - [第六阶段 练虚期(4-6 周,每周 8-10 小时)](#%E7%AC%AC%E5%85%AD%E9%98%B6%E6%AE%B5-%E7%BB%83%E8%99%9A%E6%9C%9F4-6-%E5%91%A8%E6%AF%8F%E5%91%A8-8-10-%E5%B0%8F%E6%97%B6)
29 | - [目标](#%E7%9B%AE%E6%A0%87-5)
30 | - [路径](#%E8%B7%AF%E5%BE%84-5)
31 | - [心法](#%E5%BF%83%E6%B3%95-5)
32 | - [第七阶段 大乘期(终身学习)](#%E7%AC%AC%E4%B8%83%E9%98%B6%E6%AE%B5-%E5%A4%A7%E4%B9%98%E6%9C%9F%E7%BB%88%E8%BA%AB%E5%AD%A6%E4%B9%A0)
33 | - [目标](#%E7%9B%AE%E6%A0%87-6)
34 | - [路径](#%E8%B7%AF%E5%BE%84-6)
35 | - [心法](#%E5%BF%83%E6%B3%95-6)
36 | - [许可协议](#%E8%AE%B8%E5%8F%AF%E5%8D%8F%E8%AE%AE)
37 |
38 |
39 |
40 | # Kubernetes 学习路径
41 |
42 | ## 背景
43 |
44 | **本文由 [才云科技(Caicloud)](https://caicloud.io/) 于 2019 年内部推出,现以开源的形式进行维护**
45 |
46 | 目前云计算行业对于 [Kubernetes](https://kubernetes.io/) 学习的需求日益增加,但市面上关于 Kubernetes 的资源良莠不齐,存在几个问题:
47 |
48 | - 官方文档缺少明确的"梯度",信息错综复杂
49 | - 资料较为分散,查找信息费时费力
50 | - Kubernetes 发展很快,书籍或者网上教程容易过时
51 |
52 | 本文档旨在为广大从业者提供一个 Kubernetes 学习路径,为大家提供一定的指引。我们最终的目标是让所有人剥茧抽丝般地了解 Kubernetes,不仅仅知道怎么用 Kubernetes,还知道 Kubernetes 各个功能是如何设计的。在学习路径后期,我们还可以很"自然"的联想到正确的设计思路。
53 |
54 | ## 学习路径
55 |
56 | **注意**:
57 |
58 | - 术语来自才云科技工程师 [gaocegege](https://github.com/gaocegege) 所著《[适合系统工程师的"机器学习"学习路径](https://github.com/caicloud/mlsys-ladder)》
59 | - 注意这是学习路径,不是一个教程!
60 | - 大多数概念都会给出官方链接,如果需要深入了解请自行查找!
61 |
62 | ### 第一阶段 炼气期(2-4 周,每周 3-5 小时)
63 |
64 | #### 目标
65 |
66 | - Kubernetes 的背景
67 | - 安装 Kubernetes 环境
68 | - Kubernetes 基本概念和使用方法
69 |
70 | #### 路径
71 |
72 | 学习任何系统的之前,了解其出现的背景和意义都是必不可少的,为什么会出现 Kubernetes?它解决了什么问题?有没有其他类似的系统?这里推荐阅读才云科技 CEO 张鑫在 2017 年文章《[从风口浪尖到十字路口,写在 Kubernetes 两周年之际](https://mp.weixin.qq.com/s/hrgXzt7YKVf6ZCFzJ-WTFA)》。
73 |
74 | 接下来,在了解 Kubernetes 系统本质之前,我们需要对 Kubernetes 有一个较为"感性"的认识,打消对 Kubernetes 的畏难情绪。这里,我们推荐使用 [minikube](https://github.com/kubernetes/minikube) 或 [kind](https://github.com/kubernetes-sigs/kind) 部署一个本地环境,然后开始部署一个"真实"的应用(minikube 安装需要使用科学上网,或使用[“国内版” minikube](https://yq.aliyun.com/articles/221687))。如果想一开始就挑战更高难度的安装方式(不推荐),可以使用 [kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/) 或者手动部署所有组件。关于安装,可以参考文档 [lab1-installation](https://github.com/caicloud/kube-ladder/blob/master/tutorials/lab1-installation.md)。
75 |
76 | 在安装好环境之后,可以开始动手实践最基本的 Kubernetes 概念。在第一阶段,我们推荐熟练使用以下常用资源和概念:Pod、Node、Label、Event、Service、Configmap & Secret、Deployment、Namespace。相关学习可以参考文档 [lab2-application-and-service](https://github.com/caicloud/kube-ladder/blob/master/tutorials/lab2-application-and-service.md)。
77 |
78 | (可选)仅完成上述内容可能还不足以让我们非常熟悉 Kubernetes 的基本概念,下面列出其他可以参考的资料,大家也可以按照自己的方式去搜索相关的资料:
79 | - 官方 Tutorial:[Learn Kubernetes Basics](https://kubernetes.io/docs/tutorials/kubernetes-basics/)
80 | - 官方 Guestbook 样例:[Guestbook Example](https://kubernetes.io/docs/tutorials/stateless-application/guestbook/)
81 | - [Kubernetes Tutorial for Beginners](https://spacelift.io/blog/kubernetes-tutorial)
82 |
83 | #### 心法
84 |
85 |
🤨
86 |
87 | - 请反复加深对上面资源的操作熟练度。如果你是第一次接触 Kubernetes,或者仅了解过一点 Kubernetes 的知识,那么基(ken)本(ding)是不明白 Kubernetes 底层到底发生了什么。请不要心急,姑且把它当成一个黑盒工具即可 🛠。
88 | - 你可能会在网上看到更多的概念,如 PVC、Ingress、Priority 等。炼气阶段,请不要尝试学习过多的资源类型。Kubernetes 有非常多的概念和类似的资源,我们这里熟悉最核心的概念即可,否则易走火入魔 👻,切记。当我们打通任督二脉之时,所有的新概念都不过尔尔。
89 |
90 | ### 第二阶段 筑基期(4-6 周,每周 8-10 小时)
91 |
92 | #### 目标
93 |
94 | - Kubernetes 的基本架构
95 | - Kubernetes 容器调度的基本流程
96 |
97 | #### 路径
98 |
99 | 短暂接触 Kubernetes 概念之后,我们需要知其然并且知其所以然,因此在第二阶段我们开始学习 Kubernetes 基本架构。学习 Kubernetes 基本架构至少需要了解以下内容:
100 |
101 | - Master & Node
102 | - 知道什么是 Kubernetes Master,什么是 [Node](https://kubernetes.io/docs/concepts/architecture/nodes/)
103 | - 知道两者的关系,知道它们是如何通信的
104 | - Master 组件
105 | - API Server。Kubernetes 如何接收请求,又是如何将结果返回至客户端。
106 | - [Etcd](https://etcd.io/docs)。了解 Etcd 主要功能机制。
107 | - Controller Manager。Kubernetes 控制器是其架构中最为核心的一环,我们需要了解控制器的原理,List-Watch 的基本原理,知道 Kubernetes 默认情况下大致包含哪些类型的控制器。
108 | - [Scheduler](https://kubernetes.io/docs/concepts/scheduling/kube-scheduler/)。熟悉 Kubernetes 的调度流程是怎样的,调度器在整个调度流程中的角色。
109 | - Node 组件
110 | - Kubelet。知道 Kubelet 是如何接受调度请求并启动容器的。
111 | - Kube-proxy。了解 Kube-proxy 的作用,提供的能力是什么。
112 | - Container Runtime。了解都有哪些 Container Runtime,主要了解 [Docker](https://docs.docker.com/) 一些基本操作与实现原理。
113 | - 核心 Addons & Plugins
114 | - DNS。DNS 为集群的服务发现提供的支持,Kubernetes 1.13 开始默认使用 [CoreDNS](https://coredns.io/)。
115 | - Network Plugin。Kubernetes 多节点环境需要部署网络插件才可以使用,默认情况下使用 [flannel](https://github.com/coreos/flannel) 即可。
116 |
117 | 首先可以阅读书籍或网上博客,推荐阅读:
118 |
119 | - 官方文档:[Kubernetes Components](https://kubernetes.io/docs/concepts/overview/components/)
120 | - feisky 的博客:[Kubernetes 指南之核心原理](https://kubernetes.feisky.xyz/concepts/index)
121 | - kubectl run 的背后流程(难):[What happens when I type kubectl run?](https://github.com/jamiehannaford/what-happens-when-k8s)
122 | - kubectl run 的背后流程中文版:[kubectl 创建 Pod 背后到底发生了什么?](https://mp.weixin.qq.com/s/ctdvbasKE-vpLRxDJjwVMw)
123 |
124 | 接下来,推荐从 0 开始部署一个 Kubernetes 集群(不使用任何工具),来加深对各个组件的理解:解决部署中出现的各种问题,查看组件启动日志等等。如果时间有限,也可以尝试使用 kubeadm 等工具来部署集群。目前 Kubernetes 集群部署自动化已经做得比较完善,但出于学习目的,再次墙裂推荐手动安装。关于手动安装集群,可以参考文档 [lab3-manual-installtion](https://github.com/caicloud/kube-ladder/blob/master/tutorials/lab3-manual-installtion.md)。
125 |
126 | 在本阶段修炼结束后,我们至少应该对以下问题了如指掌:Kubernetes 组件是如何交互,来启动容器,并对外提供服务的?
127 |
128 | #### 心法
129 |
130 | 💪
131 |
132 | - 请不要死记硬背 Kubernetes 架构,要开动大脑 🧠去理解其背后设计的原因。
133 | - 筑基期是比较困难的一个阶段,如果感觉一头雾水,请不要气馁,你不是一个人。当你感觉进入了瓶颈时,可以尝试寻找身边的战友,总结一些你的问题并寻求答案 🍻。
134 |
135 | ### 第三阶段 金丹期(2-4 周,每周 3-5 小时)
136 |
137 | #### 目标
138 |
139 | - Kubernetes API 结构
140 | - 熟悉 Kubernetes 各个子系统
141 | - 熟悉 Kubernetes 排错相关内容
142 |
143 | #### 路径
144 |
145 | 当我们可以熟练使用 Kubernetes 的基本资源,并且对 Kubernetes 的基本架构有了充足了认识,接下来需要对 Kubernetes 的 API 结构和子系统要有一个比较全面的认识,同时也要开始更加系统的了解排查问题相关的内容。
146 |
147 | 要知道 [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/) 是其最引以为傲的设计,掌握 API 的关键是需要了解:
148 |
149 | - Kubernetes 的 API 是如何控制版本的
150 | - Kubernetes 的 API 是如何分组的
151 | - [Kubernetes 对象](https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/)的表示方法与设计理念
152 | - [Kubernetes API 的访问控制](https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/)
153 |
154 | 我们可以通过浏览 [Kubernetes API](https://github.com/kubernetes/api) 代码仓库来了解 Kubernetes API 组(Group)的信息。所有的资源定义代码都遵循 `//types.go` 的规范,例如上述 Deployment 资源是定义在 [apps group](https://github.com/kubernetes/api/tree/master/apps) 中。我们可以在 [apps/v1/types.go](https://github.com/kubernetes/api/blob/master/apps/v1/types.go) 中查找到关于 Deployment 的定义。
155 |
156 | 接下来,我们可以通过浏览 [Kubernetes/Community](https://github.com/kubernetes/community) 代码仓库来了解各个兴趣小组(SIG),"SIG" 是 Special Interest Group 的简称。Kubernetes 的演进都是通过 SIG 来推动的,因此了解 SIG 的分工对我们理解 Kubernetes 非常重要。一般来讲,一个 SIG 对应着一个 Kubernetes 子系统,例如,[sig-apps](https://github.com/kubernetes/community/tree/master/sig-apps) 负责决定是否引入新的 API,或者现有 API 是否需要升级等等。我们通过查看 Community 中带有 "sig-" 前缀的目录来了解 SIG 的工作内容、会议纪要等等。这里简单列举 Kubernetes 重要的子系统:
157 |
158 | - 架构 Architecture
159 | - 应用 Apps
160 | - 存储 Storage
161 | - 网络 Network
162 | - 权限 Auth
163 | - 节点 Node
164 | - 调度 Scheduling
165 | - 命令行 CLI
166 | - 多集群 MultiCluster
167 | - 云平台 CloudProvider
168 | - 扩展性 Scalability
169 | - 弹性伸缩 Autoscaling
170 | - 监控日志 Instrumentation
171 |
172 | (可选)细心的你可能会发现以 "wg-" 开头的目录,例如 "wg-resource-management"。"wg" 是 working group 的简称,是针对需要涉及多个 SIG 之间合作而展开的一种工作组,独立于任何 SIG 。例如 resource management 会涉及到 Node、Storage、Scheduling 等 SIGs。
173 |
174 | 作为一个承上启下的阶段,我们需要总结一些 Kubernetes 排错的能力,推荐阅读:
175 |
176 | - 官方文档:[Kubernetes Troubleshooting](https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/)
177 | - feisky 的博客:[Kubernetes 集群排错指南](https://feisky.gitbooks.io/kubernetes/troubleshooting/)
178 |
179 | #### 心法
180 |
181 | 🌱
182 |
183 | - 本阶段的重点是"耳听六路 :see_no_evil: 眼观八方 :hear_no_evil:"。前两个阶段接触到了很多 Kubernetes 的细节,本阶段需要对 Kubernetes 的全貌有个更加清晰的认识。很多内容可能看不太懂,但请在你的心中埋下一颗种子。
184 |
185 | ### 第四阶段 元婴期(4-6 周,每周 8-10 小时)
186 |
187 | #### 目标
188 |
189 | - 加深对各个资源的理解
190 | - 学习更多 Kubernetes 概念和知识
191 |
192 | #### 路径
193 |
194 | 不出意外,你现在对 Kubernetes 基本的资源已经很熟练了,对 Kubernetes 内部组件和它们的交互比较清晰,还对 Kubernetes 的 API 全貌和组织结构也有一定的了解。如果出了意外 🤔,请重新回顾你的学习过程。
195 |
196 | 本阶段,我们围绕几个关键方向来学习 Kubernetes,加深对其各个技术点的认识(这里只列出本阶段需要学习的核心能力,其他功能请量力而学):
197 |
198 | - 计算
199 | - [Pod Lifecycle & Healthcheck & RestartPolicy](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/)
200 | - [Pod Init-Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)
201 | - [Horizontal Pod Autoscaler (HPA)](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/)
202 | - 更多控制器:[Job](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/)、[CronJob](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/)、[Daemonset](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)、[StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/)、[ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)
203 |
204 | - 网络
205 | - [Service](https://kubernetes.io/docs/concepts/services-networking/service/) 实现,主要了解 [iptables](https://linux.die.net/man/8/iptables) 的实现(可选:[ipvs](https://kubernetes.io/blog/2018/07/09/ipvs-based-in-cluster-load-balancing-deep-dive/) 模式)
206 | - [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) 原理和常用的 [nginx ingress](https://github.com/kubernetes/ingress-nginx) 操作
207 | - [DNS](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) 服务的原理,以及 [CoreDNS](https://coredns.io/) 方案
208 |
209 | - 存储
210 | - [Volume](https://kubernetes.io/docs/concepts/storage/volumes/) 以及底层存储类型
211 | - [PV/PVC](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)、[StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/)
212 |
213 | - 安全
214 | - [AuthN](https://kubernetes.io/docs/reference/access-authn-authz/authentication/), [AuthZ](https://kubernetes.io/docs/reference/access-authn-authz/authorization/) & [Admission Control](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/)
215 | - [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
216 | - [ServiceAccount](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)
217 | - [Pod/Container SecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
218 | - [Pod Security Policy (PSP)](https://kubernetes.io/docs/concepts/policy/pod-security-policy/)
219 |
220 | - 调度
221 | - [Pod/Node Affinity & Anti-affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity)
222 | - [Taint & Toleration](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/)
223 | - [Priority & Preemption](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/)
224 | - [Pod Disruption Budget](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/)
225 |
226 | 总结一下,1)本阶段我们接触到更多的资源,包括:HPA、Job、CronJob、DaemonSet、StatefulSet、Ingress、Volume、PV/PVC、StorageClass、NetworkPolicy、PSP。2)更加深入了解已学资源的使用,例如 Init-Container、SecurityContext、Affinity 等。这些能力最终都会体现在各个资源的 API 上,例如 Affinity 是 Pod API 结构的一个字段,Scheduler 通过解析这个字段来进行合理的调度。未来如果有更多的能力,我们都可以通过解读不同资源的 API 字段来一探究竟。
227 |
228 | 本阶段相关学习可以参考文档 [lab4](https://github.com/caicloud/kube-ladder/blob/master/tutorials/lab4-concepts.md)。
229 |
230 | #### 心法
231 |
232 | 🧘♂️🧘♀️
233 |
234 | - 本阶段难度指数高,请合理调整你的心境。渡劫 :volcano: 成功后,你对 Kubernetes 的掌握将会进入一个新的台(tian)阶(keng)。
235 | - 学习相关功能时,可以回顾其所在 SIG,看看能不能发现有用的资源。
236 |
237 | ### 第五阶段 化神期(3-5 周,每周 6-8 小时)
238 |
239 | #### 目标
240 |
241 | - 学习更多 Kubernetes 集群层面的功能
242 | - 更加深入学习 Kubernetes 架构和组件能力
243 |
244 | #### 路径
245 |
246 | 当我们了解了 Kubernetes API 的设计理念,学习到了足够多的 API 资源及其使用方法之后,让我们再回顾一下 Kubernetes Master & Node 架构,以及它们运行的组件。事实上,Kubernetes 的每个组件都有很强的可配置性和能力,我们可以围绕 Kubernetes 的每个组件,来学习 Kubernetes 较为“隐晦”的功能。
247 |
248 | 推荐通过 Kubernetes Command Line Reference 来了解这些组件的配置:
249 | - [kube-api-server](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/)
250 | - [kube-scheduler](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-scheduler/)
251 | - [kube-controller-manager](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/)
252 | - [kube-proxy](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/)
253 | - [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)
254 | - [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/)
255 |
256 | 同时,Kubernetes 提供了 [FeatureGate](https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/) 来控制不同的特性开关,我们可以通过 FeatureGate 来了解 Kubernetes 的新特性。此外,为了方便开发者和配置管理,Kubernetes 把所有配置都挪到了相对应的 GitHub 代码仓库中,即:
257 | - https://github.com/kubernetes/kube-scheduler
258 | - https://github.com/kubernetes/kube-controller-manager
259 | - https://github.com/kubernetes/kube-proxy
260 | - https://github.com/kubernetes/kubelet
261 | - https://github.com/kubernetes/kubectl
262 |
263 | 当然,直接裸看配置有点硬核。为方便入手,下面我们简单总结部分功能(笼统的分为 Master 和 Node):
264 |
265 | *Master*
266 |
267 | - [Dynamic Admission Control](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/)
268 | - 动态准入控制(在练虚期阶段需要更加深入的了解)
269 | - 对应 API Server `--admission-control-config-file` 参数
270 | - [Advanced Auditing](https://kubernetes.io/docs/tasks/debug-application-cluster/audit)
271 | - 提供可动态配置的审计功能
272 | - 对应 API Server 带有 `--audit-` 前缀的参数
273 | - [Etcd Configuration](https://github.com/etcd-io/etcd/blob/master/Documentation/op-guide/configuration.md)
274 | - 提供各种与 Etcd 相关的配置,例如 Kubernetes event TTL
275 | - 对应 API Server 带有 `--etcd-` 前缀的参数
276 | - [All Admission Controllers](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/)
277 | - 列举所有 Kubernetes 所支持的 Admission Controllers,每个 Admission 都与 Kubernetes 特定的功能相关联
278 | - 对应 API Server `--enable-admission-plugins` 参数,该参数注释列举了所有的默认 Admission Controllers
279 | - [Garbage Collection](https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/)
280 | - 启用后,Kubernetes 会自动根据 `OwnerReferences` 来回收 API 资源
281 | - 对应 Controller-Manager `--enable-garbage-collector` 参数
282 | - Concurrent Sync Limiting
283 | - 避免过多的资源同步导致集群资源的消耗
284 | - 对应 Controller-Manager 带有 `--concurrent` 前缀的参数
285 | - All Controllers
286 | - 列举所有 Kubernetes 所支持的 Controllers,每个 Controller 都与 Kubernetes 特定的功能相关联
287 | - 对应 Controller-Manager `--controllers`,该参数注释列举了所有的默认 Controllers
288 |
289 | 其它值得注意的参数包括:
290 | - API-Server `--max-requests-inflight`, `--min-request-timeout`
291 | - API-Server `--watch-cache`, `--watch-cache-sizes`
292 | - Controller-Manager `--node-eviction-rate`
293 | - Controller-Manager `--pod-eviction-timeout`
294 | - Controller-Manager `--terminated-pod-gc-threshold`
295 | - Controller-Manager `--pv-recycler-minimum-timeout-*`
296 |
297 | *Node*
298 |
299 | - [Kubelet Eviction](https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/)
300 | - 当节点资源不足时,Kubernetes 通过驱逐 Pods 的方式确保节点的稳定性
301 | - 对应 Kubelet 带有 `--eviction-` 前缀的参数,例如 `--eviction-hard`
302 | - [Image GC](https://kubernetes.io/docs/concepts/cluster-administration/kubelet-garbage-collection/)
303 | - 清理容器镜像占用的磁盘空间
304 | - 对应 Kubelet 带有 `--image-gc-` 前缀的参数,以及 `--minimum-image-ttl-duration` 等参数
305 | - [Resource Reserve](https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/)
306 | - 为系统资源预留一定的资源,确保节点的稳定性
307 | - 对应 Kubelet `--kube-reserved`、`--kube-reserved-cgroup` 等参数
308 | - [CPU Manager](https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/)
309 | - 提供更多的 CPU 管理能力,例如静态 CPU 亲和性
310 | - 对应 Kubelet `--cpu-manager-*` 前缀的参数
311 | - [Storage Limit](https://kubernetes.io/docs/concepts/storage/storage-limits)
312 | - 避免节点过度挂载数据卷
313 | - 对应 FeatureGate `AttachVolumeLimit`
314 |
315 | 其它值得注意的参数包括:
316 | - Kubelet & Kubeproxy `--hostname-override`
317 | - Kubelet `--cgroups-per-qos`
318 | - Kubelet `--fail-swap-on`
319 | - Kubelet `--host-*`
320 | - Kubelet `--max-pods`, `--pods-per-core`
321 | - Kubelet `--resolv-conf`
322 | - Kubeproxy `--nodeport-addresses`
323 |
324 | #### 心法
325 |
326 | 😇
327 |
328 | - 通过组件配置学习 Kubernetes 功能是我们需要具备的一个常规能力,或许比较枯燥,但对我们的修炼大有裨益。
329 | - 如果你对 Kubernetes “无穷无尽”的功能感到有点迷茫,这是一个很正常的现象。除非是深度参与 Kubernetes 的开发,否则一定会有很多遗漏的地方。我们只要保持两个基本点不动摇:1. 懂 Kubernetes 架构和最核心的能力;2. 懂得怎么快速定位我们需要的能力。关于第二点,我们将在大乘期介绍,stay tuned!
330 |
331 | ### 第六阶段 练虚期(4-6 周,每周 8-10 小时)
332 |
333 | #### 目标
334 |
335 | - 对 Kubernetes 的扩展机制了如指掌
336 | - 可以编写 Kubernetes 控制器,能够基于扩展机制灵活地二次开发
337 |
338 | #### 路径
339 |
340 | 本阶段我们可以开始了解 Kubernetes [各种扩展机制](https://kubernetes.io/docs/concepts/extend-kubernetes/extend-cluster/)。如果说 Kubernetes 的 API 和架构设计是其重要的基石,那么扩展机制使得 Kubernetes 在各个生态领域开花结果。下面我们尝试列举出所有的扩展方式,每一种扩展都有其优势和局限性,请自行思考。注意这里提到的扩展机制指的是架构上的扩展,而非功能层面的扩展,例如 Pod 支持各种 Probe 来进行健康检查,包括自定义,这里我们不归为扩展机制的能力。
341 |
342 | *API 资源扩展能力*
343 |
344 | - [Annotation](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/):保存少量非结构化第三方数据
345 | - [Finalizer](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#finalizers):资源删除时,用户调用外部系统的钩子
346 | - [CustomResourceDefinition](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/):自定义 Kubernetes API
347 | - [API Aggregation](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/):多个 API Server 聚合,适用于较大量的 API 定制
348 |
349 | 学习 API 资源扩展的一个重要方式是创建一个扩展资源,或者编写一个自己的控制器。强烈推荐自行编写一个控制器,这里列出几个常见的工具:
350 |
351 | - [kubebuilder](https://book.kubebuilder.io/):来自 Kubernetes 官方的 API 扩展项目
352 | - [sample-controller](https://github.com/kubernetes/sample-controller):来自 Kubernetes 官方的一个样例
353 | - [operator-sdk](https://github.com/operator-framework/operator-sdk):来自红帽的一个 operator 库
354 | - [shell-operator](https://github.com/flant/shell-operator):适合运维开发使用的 shell operator 库
355 | - [meta-controller](https://metacontroller.app/):来自 Google 的一个更加"傻瓜"式编写控制器的库
356 |
357 | *API 访问扩展能力*
358 |
359 | - [认证 Webhook](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication):用户认证时,调用外部服务,仅支持静态配置
360 | - [鉴权 Webhook](https://kubernetes.io/docs/reference/access-authn-authz/webhook/):用户鉴权时,调用外部服务,仅支持静态配置
361 | - [动态访问控制 Webhook](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/):请求访问控制时,调用外部服务,支持动态增加外部服务
362 |
363 | Kubernetes API 访问扩展主要是通过 Webhook 来实现。注意只有访问控制支持动态增加外部服务,认证鉴权的外部服务在启动 API Server 的时候就注册完毕,无法在后续增加,主要原因是动态增加外部认证鉴权服务,带来的安全风险过大。
364 |
365 | *调度器扩展能力*
366 |
367 | - [扩展接口(Scheduler Extender)](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/scheduler_extender.md):类似 Webhook,调用外部服务进行调度决策
368 | - [多调度器](https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/):支持在 Kubernetes 运行多个调度器调度不同作业
369 | - [调度器框架](https://kubernetes.io/docs/concepts/configuration/scheduling-framework/):定义一套 Go API,使用户无需 fork Kubernetes Scheduler 代码即可完成“代码级”的定制
370 |
371 | 针对简单场景,我们可以直接使用 Scheduler Extender 即可,例如按 GPU 型号调度。复杂调度场景可以使用多调度器或调度器框架,例如基于流图的调度器 [poseidon](https://kubernetes.io/docs/concepts/extend-kubernetes/poseidon-firmament-alternate-scheduler/),批处理调取器 [kube-batch](https://github.com/kubernetes-sigs/kube-batch) 等。一般而言,使用 Extender 即可满足大多数场景。
372 |
373 | *网络扩展能力*
374 |
375 | - [网络插件 CNI](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/):使用 CNI 插件,可以选择任何我们需要的[网络方案](https://kubernetes.io/docs/concepts/cluster-administration/networking/)
376 | - [自定义 Ingress 控制器](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/):Ingress 定义了一套 API 接口,我们可以选择任意实现
377 | - [自定义 NetworkPolicy 控制器](https://kubernetes.io/docs/concepts/services-networking/network-policies/):同上,可选实现包括 [Calico](https://kubernetes.io/docs/tasks/administer-cluster/network-policy-provider/calico-network-policy/)、[Cilium](https://kubernetes.io/docs/tasks/administer-cluster/network-policy-provider/cilium-network-policy/) 等
378 | - [自定义 DNS 控制器](https://github.com/kubernetes/dns/blob/master/docs/specification.md):Kubernetes 定义了一套 DNS 规范,我们可以选择任意实现
379 |
380 | 网络插件 CNI 是容器网络标准,Kubernetes 提供了良好的支持,常用插件包括 flannel、Calico 等等。对于 Ingress、NetworkPolicy、DNS,相信到目前为止大家应该可以理解,其本质上是 Kubernetes 定义的一套 API,底层实现可插拔,用户可以有自己的选择。
381 |
382 | *存储扩展能力*
383 |
384 | - [FlexVolume](https://kubernetes.io/docs/concepts/storage/volumes/#flexVolume):Kubernetes 提供的一种动态对接存储方案,支持用户自定义存储后端
385 | - [存储插件 CSI](https://kubernetes-csi.github.io):使用 CSI 插件,可以选择任何我们需要的存储方案
386 |
387 | FlexVolume 是 Kubernetes 自带的对接外部存储的方案,用户编写少量的代码即可加入自定义存储后端,适用于简单场景。存储插件 CSI 是容器网络标准,Kubernetes 提供了良好的支持,同时为方便第三方实现,还提供了一整套 SDK 解决方案。所有底层存储相关的能力都与 CSI 密切相关。
388 |
389 | *运行时扩展能力*
390 |
391 | - [运行时接口 CRI](https://kubernetes.io/docs/setup/production-environment/container-runtimes/):使用 CRI 插件,可以选择任何我们需要的运行时方案
392 |
393 | 运行时接口 CRI 是 Kubernetes 提出,为解决支持多种运行时而提供的方案。任何运行时,只需实现 CRI 相关的接口,即可接入 Kubernetes 中,包括 Docker、Containerd、gVisor、Kata 等。
394 |
395 | *特殊硬件或资源扩展能力*
396 |
397 | - [扩展资源 Extended Resource](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#extended-resources):通过 Kubernetes 原生 API 方式支持添加自定义资源
398 | - [设备插件 Device Plugin](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/):使用 Device Plugin 插件,可以对接任何我们需要的硬件
399 |
400 | 对于简单场景,例如静态汇报资源数量,可以直接使用 Extended Resource 扩展 Kubernetes 所支持的硬件。Device Plugin 的核心是自动接入各种特殊硬件如 Nvidia、Infiniband、FPGA 等。在资源汇报层面 Device Plugin 目前也使用了 Extended Resource 的能力,但由于 Extended Resource 的局限性,Device Plugin 未来也可以与其他 API 对接。目前使用最多的 Device Plugin 主要是 Nvidia 的 [GPU device plugin](https://github.com/NVIDIA/k8s-device-plugin)。
401 |
402 | *监控扩展能力*
403 |
404 | - [自定义监控](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-metrics-apis):支持使用自定义监控组件如 Prometheus 提供监控指标
405 |
406 | 自定义监控包括 Custom Metrics 和 External Metrics,例如 [Prometheus adaptor](https://github.com/DirectXMan12/k8s-prometheus-adapter)。
407 |
408 | *云供应商扩展能力*
409 |
410 | - [云控制器 Cloud Controller Manager](https://kubernetes.io/docs/concepts/architecture/cloud-controller/):支持可插拔云服务提供商
411 |
412 | 云扩展能力的目标是使各个云供应商可以在不改变 Kubernetes 源码的情况下,接入其服务。每个云供应商都有[独立的项目](https://github.com/kubernetes?utf8=%E2%9C%93&q=cloud-provider&type=&language=)。
413 |
414 | *命令行插件*
415 |
416 | - [Kubectl Plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/):kubectl plugin 支持扩展 kubectl 子命令,与 API 扩展能力结合可以提供近乎原生的使用方法。
417 |
418 | #### 心法
419 |
420 | :godmode:
421 |
422 | - 推荐实现一个端到端的 Kubernetes 控制器,可以对整个 Kubernetes 的二次开发有更加深入的了解。此外,针对所有的扩展能力,建议先建立一个全面的认识,再根据需要深入某一项能力。
423 | - 我们除了通过用户手册来学习上面的技术,也可多参考 Kubernetes 的花式设计文档,主要是 [Design Proposals](https://github.com/kubernetes/community/tree/master/contributors/design-proposals)、[KEPs](https://github.com/kubernetes/enhancements/tree/master/keps)。
424 |
425 | ### 第七阶段 大乘期(终身学习)
426 |
427 | #### 目标
428 |
429 | - 了解 Kubernetes 生态项目
430 | - 跟踪 Kubernetes 社区发展
431 | - 跟踪 CNCF 社区发展
432 |
433 | #### 路径
434 |
435 | 目前为止,我们学习了很多 Kubernetes 的概念,但也只是其最重要的部分。在本阶段,我们需要专注以下几个问题:
436 |
437 | - 如何跟进 Kubernetes 的新功能,以及现有功能的更多细节?
438 | - 如何了解 Kubernetes 整个生态环境的发展?
439 |
440 | 首先,让我们一起来学习几个重要的项目。围绕 Kubernetes 的生态环境建设是其成为容器标准的关键。
441 |
442 | - [Helm](https://github.com/helm/helm):作为 Kubernetes 生态里的 brew、dnf、dpkg,Helm 为 Kubernetes 提供了包管理能力,方便用户快速部署安装各种服务。
443 | - [Harbor](https://github.com/goharbor/harbor):Harbor 与 Kubernetes 无直接关系,但作为云原生环境下最常用的镜像仓库解决方案,了解 Harbor 十分重要。
444 | - [Prometheus](https://prometheus.io/):Prometheus 是云原生环境下最重要的监控组件。
445 | - [Istio](https://istio.io/):Istio 是服务网格的关键项目,但较为复杂,可以尝试简单了解。
446 |
447 | 以上,我们仅列出了极少量的重要项目,Kubernetes 周边的项目十分之多,令人咂舌 😱。因此大乘期的你,需要开始持续跟踪 Kubernetes 及其生态的发展,甚至可以推动其发展,接下来我们列举一些靠谱资源:
448 |
449 | *GitHub 仓库*
450 |
451 | - [Kubernetes Enhancement](https://github.com/kubernetes/enhancements/):关注新特性的讨论
452 | - [Kubernetes Community](https://github.com/kubernetes/community):关注社区组织情况
453 | - [CNCF TOC](https://github.com/cncf/toc/):关注 CNCF 进展,各种新项目讨论等
454 | - [Awesome Kubernetes](https://github.com/ramitsurana/awesome-kubernetes):Kubernetes 项目之学不动系列
455 |
456 | 关注 GitHub 仓库可以让你了解最一手的进展,但是信息量一般较大,讨论很多难度也比较大。不过对于大乘期的你来讲,应该不是问题 😉。另外,这里还包含很多 Kubernetes 系统内部的设计,例如调度器的优化方案、资源垃圾回收方案等,值得了解和学习。
457 |
458 | *Twitter 账号*
459 |
460 | 下面推荐几个 Kubernetes 项目的核心人员。大牛都喜欢用 Twitter 交(si)流(bi),可以关注一波。感兴趣的话题可以去交流,大牛都十分耐撕(nice。
461 |
462 | - [Tim Hockin](https://twitter.com/thockin)
463 | - [Clayton Coleman](https://twitter.com/smarterclayton)
464 | - [Daniel Smith](https://twitter.com/originalavalamp)
465 | - [Brian Grant](https://twitter.com/bgrant0607)
466 | - [Vishnu Kannan](https://twitter.com/vishnukanan)
467 | - [Saad Ali](https://twitter.com/the_saad_ali)
468 | - [Kelsey Hightower](https://twitter.com/kelseyhightower)
469 | - [Joe Beda](https://twitter.com/jbeda)
470 | - [Brendan Burns](https://twitter.com/brendandburns)
471 | - [Michelle Noorali](https://twitter.com/michellenoorali)
472 |
473 | 除此之外,Twitter 上还有不少项目和其他 Weekly 性质的 Twitter,推荐几个账号关注:
474 |
475 | - [Kube Weekly](https://twitter.com/kubeweekly)
476 | - [Kube List](https://twitter.com/readkubelist)
477 |
478 | Twitter 会根据你的喜好推荐其他相关内容,接下来就自由发挥。
479 |
480 | *Blog 账号*
481 |
482 | - [Kubernetes Blog](https://kubernetes.io/blog/)
483 | - [CNCF Blog](https://www.cncf.io/category/blog/)
484 | - [Caicloud Blog](https://caicloud.io/blog)
485 |
486 | 可以关注的优秀 Blog 很多,这里就不一一列举。
487 |
488 | #### 心法
489 |
490 | 🐲
491 | 请坚持学习!送上一句黑鸡汤:
492 | "The last thing you want is to look back on your life and wonder... if only."
493 |
494 |
495 | ## 许可协议
496 |
497 | - 本文遵守[创作共享 CC BY-NC-SA 3.0 协议](https://creativecommons.org/licenses/by-nc-sa/3.0/cn/)
498 | - 商业目的转载,请联系
499 | - 如有任何版权问题,请联系 和
500 |
--------------------------------------------------------------------------------
/tutorials/images/deployment_initial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/deployment_initial.png
--------------------------------------------------------------------------------
/tutorials/images/deployment_scale.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/deployment_scale.png
--------------------------------------------------------------------------------
/tutorials/images/deployment_service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/deployment_service.png
--------------------------------------------------------------------------------
/tutorials/images/deployment_update_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/deployment_update_1.png
--------------------------------------------------------------------------------
/tutorials/images/deployment_update_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/deployment_update_2.png
--------------------------------------------------------------------------------
/tutorials/images/deployment_update_done.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/deployment_update_done.png
--------------------------------------------------------------------------------
/tutorials/images/deployment_update_initial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/deployment_update_initial.png
--------------------------------------------------------------------------------
/tutorials/images/hpa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/hpa.png
--------------------------------------------------------------------------------
/tutorials/images/kubernetes_cluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/kubernetes_cluster.png
--------------------------------------------------------------------------------
/tutorials/images/labels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/caicloud/kube-ladder/7fb40dcfc4f863b473b1e110158875de44550595/tutorials/images/labels.png
--------------------------------------------------------------------------------
/tutorials/lab1-installation.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
4 |
5 | - [单机部署](#%E5%8D%95%E6%9C%BA%E9%83%A8%E7%BD%B2)
6 | - [安装 kubectl](#%E5%AE%89%E8%A3%85-kubectl)
7 | - [使用 Minikube 部署 Kubernetes](#%E4%BD%BF%E7%94%A8-minikube-%E9%83%A8%E7%BD%B2-kubernetes)
8 | - [安装](#%E5%AE%89%E8%A3%85)
9 | - [验证](#%E9%AA%8C%E8%AF%81)
10 | - [使用 Kind 部署 Kubernetes](#%E4%BD%BF%E7%94%A8-kind-%E9%83%A8%E7%BD%B2-kubernetes)
11 | - [安装](#%E5%AE%89%E8%A3%85-1)
12 | - [验证](#%E9%AA%8C%E8%AF%81-1)
13 | - [其它开源安装工具](#%E5%85%B6%E5%AE%83%E5%BC%80%E6%BA%90%E5%AE%89%E8%A3%85%E5%B7%A5%E5%85%B7)
14 |
15 |
16 |
17 | # 单机部署
18 |
19 | ## 安装 kubectl
20 |
21 | Kubectl 是 Kubernetes 自带的命令行工具,可以用它直接操作 Kubernetes。
22 |
23 | macOS,执行:
24 |
25 | ```bash
26 | # using brew https://brew.sh/
27 | brew install kubernetes-cli
28 | ```
29 |
30 | Linux,执行:
31 |
32 | ```bash
33 | curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
34 | && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
35 | ```
36 |
37 | Windows,执行:
38 |
39 | ```bash
40 | curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe
41 | ```
42 |
43 | ## 使用 Minikube 部署 Kubernetes
44 |
45 | [Minikube](https://github.com/kubernetes/minikube) 用于本地部署 kubernetes 集群,支持 macOS,Linux,和 Windows。
46 |
47 | **注意**:**科学上网**是必须的,否则 minikube iso 镜像文件,gcr.io 的 Docker 镜像等将无法下载。
48 |
49 | ### 安装
50 |
51 | **下载依赖**:
52 |
53 | * *macOS 10.12 (Sierra)*
54 | * 要求安装 hypervisor,比如 [hyperkit](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver) (推荐)或 [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
55 | * 使用 [brew](https://brew.sh/) : `brew cask install minikube`
56 | * 或者使用 curl: `curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 && sudo install minikube-darwin-amd64 /usr/local/bin/minikube`
57 |
58 | * *Windows 10*
59 | * 要求安装 hypervisor,比如 [VirtualBox](https://www.virtualbox.org/wiki/Downloads) (推荐)或 [HyperV](https://docs.docker.com/machine/drivers/hyper-v/)
60 | * BIOS 中必须开启 VT-x/AMD-v virtualization
61 | * 使用 [chocolatey](https://chocolatey.org/) `choco install minikube`
62 | * 或者通过链接下载: Download and run the [installer](https://storage.googleapis.com/minikube/releases/latest/minikube-installer.exe)
63 |
64 | * *Linux*
65 | * 要求安装 [kvm2 driver](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#kvm2-driver) (推荐)或 [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
66 | * BIOS 中必须开启 VT-x/AMD-v virtualization
67 | * 使用 curl: `curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && sudo install minikube-linux-amd64 /usr/local/bin/minikube`
68 |
69 | **确认你的 minikube 至少是 v1.2.0**:
70 |
71 | ```sh
72 | $ minikube version
73 | minikube version: v1.2.0
74 | ```
75 |
76 | **启动 Minikube**:
77 |
78 | **注意**: 这里我们使用的是 VirtualBox,如果你用的其它,可能会需要另外的配置,请按照上一节 👆 的链接查找。
79 |
80 | ```sh
81 | $ minikube start
82 | 😄 minikube v1.2.0 on darwin (amd64)
83 | 🔥 Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...
84 | 🐳 Configuring environment for Kubernetes v1.15.0 on Docker 18.09.6
85 | 💾 Downloading kubeadm v1.15.0
86 | 💾 Downloading kubelet v1.15.0
87 | 🚜 Pulling images ...
88 | 🚀 Launching Kubernetes ...
89 | ⌛ Verifying: apiserver proxy etcd scheduler controller dns
90 | 🏄 Done! kubectl is now configured to use "minikube"
91 | ```
92 |
93 | ### 验证
94 |
95 | 执行下面的命令:
96 |
97 | ```sh
98 | $ kubectl get nodes
99 | NAME STATUS ROLES AGE VERSION
100 | minikube Ready master 4m5s v1.15.0
101 | ```
102 |
103 | 若输出正常,则表示创建成功。
104 |
105 | ## 使用 Kind 部署 Kubernetes
106 |
107 | [Kind](https://github.com/kubernetes-sigs/kind) 是另一个 Kubernetes 集群部署工具,通过 Docker 容器 "nodes" 完成部署。
108 |
109 | **注意**: 在这之前,你必须安装 [go](https://golang.org/) 和 [docker](https://www.docker.com/),并且 go 的版本至少是 1.12.6。
110 |
111 | ### 安装
112 |
113 | ```sh
114 | $ GO111MODULE="on" go get sigs.k8s.io/kind && kind create cluster
115 | ...
116 | Creating cluster "kind" ...
117 | ✓ Ensuring node image (kindest/node:v1.15.0) 🖼
118 | ✓ Preparing nodes 📦
119 | ✓ Creating kubeadm config 📜
120 | ✓ Starting control-plane 🕹️
121 | ✓ Installing CNI 🔌
122 | ✓ Installing StorageClass 💾
123 | Cluster creation complete. You can now use the cluster with:
124 |
125 | export KUBECONFIG="$(kind get kubeconfig-path --name="kind")"
126 | kubectl cluster-info
127 | ```
128 |
129 | **注意**: 请务必执行输出中的命令,以配置 kubeconfig。
130 |
131 | ### 验证
132 |
133 | 执行下面的命令:
134 |
135 | ```sh
136 | $ kubectl get nodes
137 | NAME STATUS ROLES AGE VERSION
138 | kind-control-plane Ready master 2m54s v1.15.0
139 | ```
140 |
141 | ## 其它开源安装工具
142 |
143 | - https://github.com/bsycorp/kind
144 | - https://github.com/ubuntu/microk8s
145 | - https://github.com/kinvolk/kube-spawn
146 | - https://github.com/danderson/virtuakube
147 | - https://github.com/kubernetes-sigs/kubeadm-dind-cluster
148 |
--------------------------------------------------------------------------------
/tutorials/lab2-application-and-service.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - [Introduction](#introduction)
6 | - [Kubectl command line](#kubectl-command-line)
7 | - [kubectl version](#kubectl-version)
8 | - [kubectl cluster-info](#kubectl-cluster-info)
9 | - [kubectl -h](#kubectl--h)
10 | - [kubectl command format](#kubectl-command-format)
11 | - [kubectl config file](#kubectl-config-file)
12 | - [Refereneces](#refereneces)
13 | - [Kubernetes node](#kubernetes-node)
14 | - [Node information](#node-information)
15 | - [Node details](#node-details)
16 | - [Readings](#readings)
17 | - [Kubernetes Namespace](#kubernetes-namespace)
18 | - [Namespaces](#namespaces)
19 | - [Readings](#readings-1)
20 | - [Kubernetes Pod & Deployment](#kubernetes-pod--deployment)
21 | - [Create Deployment](#create-deployment)
22 | - [Get Deployment](#get-deployment)
23 | - [Get Pods](#get-pods)
24 | - [Get Pod Logs](#get-pod-logs)
25 | - [Execute command in Pod](#execute-command-in-pod)
26 | - [Readings](#readings-2)
27 | - [Kubernetes Service](#kubernetes-service)
28 | - [Create service](#create-service)
29 | - [Get service](#get-service)
30 | - [Query service](#query-service)
31 | - [NodePort service](#nodeport-service)
32 | - [Readings](#readings-3)
33 | - [Kubernetes Label](#kubernetes-label)
34 | - [View selector & label](#view-selector--label)
35 | - [Label operations](#label-operations)
36 | - [Readings](#readings-4)
37 | - [Kubernetes Deployment Operations](#kubernetes-deployment-operations)
38 | - [Scale up using kubectl](#scale-up-using-kubectl)
39 | - [View service](#view-service)
40 | - [Scale down using kubectl](#scale-down-using-kubectl)
41 | - [Update deployment](#update-deployment)
42 | - [Update via setting image](#update-via-setting-image)
43 | - [Deployment rollout](#deployment-rollout)
44 | - [Kubernetes Yaml/Json File](#kubernetes-yamljson-file)
45 | - [Get resource yaml](#get-resource-yaml)
46 | - [Create resource using yaml](#create-resource-using-yaml)
47 | - [Update resource yaml](#update-resource-yaml)
48 | - [Readings](#readings-5)
49 | - [Kubernetes Events](#kubernetes-events)
50 | - [Kubernetes Pod Lifecycle](#kubernetes-pod-lifecycle)
51 | - [Restart policy](#restart-policy)
52 | - [Container probes](#container-probes)
53 | - [Readings](#readings-6)
54 | - [Kubernetes ConfigMap & Secret](#kubernetes-configmap--secret)
55 | - [Readings](#readings-7)
56 | - [Summary](#summary)
57 | - [Exercise](#exercise)
58 |
59 |
60 |
61 | # Introduction
62 |
63 | 本节我们将学习基于 Kubernetes 的应用管理,包括 kubectl, pod, deployment, service, label 等等。针对每个内容都会给出 Reading List。注意,本节所有的操作都基于 [Lab1](./lab1-installation.md) 中创建的 Minikube 集群。
64 |
65 | # Kubectl command line
66 |
67 | ## kubectl version
68 |
69 | 在 kubernetes 中,我们使用 kubectl 命令与 kubernetes 交互,在下面的试验中,我们将逐渐熟悉并了解更多
70 | kubectl 相关的命令,我们可以使用 `kubectl version` 检查 kubernetes 的版本信息。
71 |
72 | ```
73 | $ kubectl version
74 | Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-20T04:52:26Z", GoVersion:"go1.12.6", Compiler:"gc", Platform:"darwin/amd64"}
75 | Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-19T16:32:14Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}
76 | ```
77 |
78 | 从以上输出可以看出,kubectl 客户端的版本是 v1.15.0,kubernetes 集群的版本是 v1.15.0。同时,该命令还会输出 kubernetes 编译信息。
79 |
80 | ## kubectl cluster-info
81 |
82 | 除了版本信息,我们还可以通过 kubectl 获取更多 kubernetes 集群的相关信息:
83 |
84 | ```
85 | $ kubectl cluster-info
86 | Kubernetes master is running at https://192.168.99.100:8443
87 | KubeDNS is running at https://192.168.99.100:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
88 |
89 | To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
90 | ```
91 |
92 | 上述信息给出了集群 API 服务的地址,如果使用 `kubectl cluster-info dump`,可以看到更多集群的信息。
93 |
94 | ## kubectl -h
95 |
96 | kubectl 提供了非常好的帮助信息,我们可以通过 `kubectl -h` 来获取帮助信息。
97 |
98 | ```
99 | $ kubectl -h
100 | kubectl controls the Kubernetes cluster manager.
101 |
102 | Find more information at: https://kubernetes.io/docs/reference/kubectl/overview/
103 |
104 | Basic Commands (Beginner):
105 | create Create a resource from a file or from stdin.
106 | expose 使用 replication controller, service, deployment 或者 pod 并暴露它作为一个 新的
107 | Kubernetes Service
108 | run 在集群中运行一个指定的镜像
109 | set 为 objects 设置一个指定的特征
110 |
111 | Basic Commands (Intermediate):
112 | explain 查看资源的文档
113 | get 显示一个或更多 resources
114 | edit 在服务器上编辑一个资源
115 | delete Delete resources by filenames, stdin, resources and names, or by resources and label selector
116 |
117 | Deploy Commands:
118 | rollout Manage the rollout of a resource
119 | scale 为 Deployment, ReplicaSet, Replication Controller 或者 Job 设置一个新的副本数量
120 | autoscale 自动调整一个 Deployment, ReplicaSet, 或者 ReplicationController 的副本数量
121 |
122 | Cluster Management Commands:
123 | certificate 修改 certificate 资源.
124 | cluster-info 显示集群信息
125 | top Display Resource (CPU/Memory/Storage) usage.
126 | cordon 标记 node 为 unschedulable
127 | uncordon 标记 node 为 schedulable
128 | drain Drain node in preparation for maintenance
129 | taint 更新一个或者多个 node 上的 taints
130 |
131 | Troubleshooting and Debugging Commands:
132 | describe 显示一个指定 resource 或者 group 的 resources 详情
133 | logs 输出容器在 pod 中的日志
134 | attach Attach 到一个运行中的 container
135 | exec 在一个 container 中执行一个命令
136 | port-forward Forward one or more local ports to a pod
137 | proxy 运行一个 proxy 到 Kubernetes API server
138 | cp 复制 files 和 directories 到 containers 和从容器中复制 files 和 directories.
139 | auth Inspect authorization
140 |
141 | Advanced Commands:
142 | diff Diff live version against would-be applied version
143 | apply 通过文件名或标准输入流(stdin)对资源进行配置
144 | patch 使用 strategic merge patch 更新一个资源的 field(s)
145 | replace 通过 filename 或者 stdin替换一个资源
146 | wait Experimental: Wait for a specific condition on one or many resources.
147 | convert 在不同的 API versions 转换配置文件
148 | kustomize Build a kustomization target from a directory or a remote url.
149 |
150 | Settings Commands:
151 | label 更新在这个资源上的 labels
152 | annotate 更新一个资源的注解
153 | completion Output shell completion code for the specified shell (bash or zsh)
154 |
155 | Other Commands:
156 | api-resources Print the supported API resources on the server
157 | api-versions Print the supported API versions on the server, in the form of "group/version"
158 | config 修改 kubeconfig 文件
159 | plugin Provides utilities for interacting with plugins.
160 | version 输出 client 和 server 的版本信息
161 |
162 | Usage:
163 | kubectl [flags] [options]
164 |
165 | Use "kubectl --help" for more information about a given command.
166 | Use "kubectl options" for a list of global command-line options (applies to all commands).
167 | ```
168 |
169 | 当我们找到需要的子命令时,可以进一步使用 -h 来查看该子命令的帮助信息:
170 |
171 | ```
172 | $ kubectl get -h
173 | ...
174 | ```
175 |
176 | ## kubectl command format
177 |
178 | kubectl 命令的基本格式是 `kubectl `,其中 `action` 可以是 `create`, `delete`, `get` 等等,`resource` 你可以使用 `kubectl api-resources` 获得完整列表。
179 |
180 | 例如,你可以通过 `kubectl get nodes` 获取节点信息,可以通过 `kubectl describe nodes ${NODENAME}` 获取节点详细信息。
181 |
182 | ## kubectl config file
183 |
184 | kubectl 通过读取配置文件信息与 kubernetes 集群交互,默认配置文件路径是 `~/.kube/config`,内容可能如下:
185 |
186 | ```
187 | $ cat ~/.kube/config
188 | apiVersion: v1
189 | clusters:
190 | - cluster:
191 | certificate-authority: /Users/deyuandeng/.minikube/ca.crt
192 | server: https://192.168.99.100:8443
193 | name: minikube
194 | contexts:
195 | - context:
196 | cluster: minikube
197 | user: minikube
198 | name: minikube
199 | current-context: minikube
200 | kind: Config
201 | preferences: {}
202 | users:
203 | - name: minikube
204 | user:
205 | client-certificate: /Users/deyuandeng/.minikube/apiserver.crt
206 | client-key: /Users/deyuandeng/.minikube/apiserver.key
207 | ```
208 |
209 | 这里有三个重要的顶级概念: `clusters`, `users` 和 `contexts`。
210 |
211 | 我们使用的集群名为 `minikube`,其服务器地址为 `https://192.168.99.100:8443`,其认证证书位于 `${HOME}/.minikube/ca.crt`。
212 |
213 | 当我们使用该 kubeconfig 发送请求时,我们充当用户 `minikube` (确切地说,真正的用户名来自证书通用名,但是我们暂时跳过它)。
214 |
215 | 最后,`context` 是各种配置的组合,例如,存在两个 `context`,一个用于集群 `minikube` 以及用户 `minikube`,另一个用于集群 `example` 和用户 `minikube`,即这意味着用户 `minikube` 可以同时访问 `minikube` 和 `example` 集群。
216 |
217 | ## Refereneces
218 |
219 | * [kubectl overview](https://kubernetes.io/docs/user-guide/kubectl-overview/)
220 |
221 | # Kubernetes node
222 |
223 | 节点(Node)是物理机或虚拟机,他们组成了 kubernetes 的资源池。Master 节点负责资源调度、集群状态控制等,
224 | Node 节点负责运行用户应用,承接负载。我们会在后续的章节中介绍具体的架构,现在我们只关心如何通过命令行根据 kubectl 与 kubernetes
225 | 接口交互管理节点。
226 |
227 | ## Node information
228 |
229 | 在 kubernetes 中,我们可以通过 `kubectl get nodes` 命令来获取所有节点信息:
230 |
231 | ```
232 | $ kubectl get nodes
233 | NAME STATUS ROLES AGE VERSION
234 | minikube Ready master 27h v1.15.0
235 | ```
236 |
237 | 以上输出表明当前集群有 1 个节点。注意,我们无法完全从命令行区分 master 节点和 node 节点。这里 minikube
238 | 节点即是 master 也是 node,也就是说,minikube 主机即负责调度和管理,也负责用户容器的运行时。一般在生产环境中,我们不会在 master 上运行用户容器。但是如果主机数量非常少的情况下可以考虑,前提是预留足够的资源给 master。
239 |
240 | 不承载用户容器的主机需要加上 SchedulingDisabled 的状态(通过 `kubectl cordon ` 实现),例如:
241 |
242 | ```
243 | $ kubectl get nodes
244 | NAME STATUS AGE
245 | i-2ze0tfg75y5plzvnd29h Ready,SchedulingDisabled 2d
246 | i-2ze0woc5l1230xs5zxry Ready 2d
247 | i-2ze14a3m7riw0l18oemg Ready 2d
248 | i-2ze14a3m7riw0l18oemh Ready 2d
249 | i-2ze1nwnt9tc3wg83rsru Ready 2d
250 | ```
251 |
252 | ## Node details
253 |
254 | 我们可以通过 `kubectl describe nodes` 来了解节点的详情。下面显示了 minikube 节点的详情,我们可以暂时不关心输出内容的细节。
255 |
256 | ```
257 | $ kubectl describe nodes minikube
258 | Name: minikube
259 | Roles: master
260 | Labels: beta.kubernetes.io/arch=amd64
261 | beta.kubernetes.io/os=linux
262 | kubernetes.io/arch=amd64
263 | kubernetes.io/hostname=minikube
264 | kubernetes.io/os=linux
265 | node-role.kubernetes.io/master=
266 | Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
267 | node.alpha.kubernetes.io/ttl: 0
268 | volumes.kubernetes.io/controller-managed-attach-detach: true
269 | CreationTimestamp: Thu, 27 Jun 2019 11:03:46 +0800
270 | Taints:
271 | Unschedulable: false
272 | Conditions:
273 | Type Status LastHeartbeatTime LastTransitionTime Reason Message
274 | ---- ------ ----------------- ------------------ ------ -------
275 | MemoryPressure False Fri, 28 Jun 2019 14:42:41 +0800 Thu, 27 Jun 2019 11:03:40 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
276 | DiskPressure False Fri, 28 Jun 2019 14:42:41 +0800 Thu, 27 Jun 2019 11:03:40 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
277 | PIDPressure False Fri, 28 Jun 2019 14:42:41 +0800 Thu, 27 Jun 2019 11:03:40 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
278 | Ready True Fri, 28 Jun 2019 14:42:41 +0800 Thu, 27 Jun 2019 11:03:40 +0800 KubeletReady kubelet is posting ready status
279 | Addresses:
280 | InternalIP: 10.0.2.15
281 | Hostname: minikube
282 | Capacity:
283 | cpu: 2
284 | ephemeral-storage: 17784772Ki
285 | hugepages-2Mi: 0
286 | memory: 2038624Ki
287 | pods: 110
288 | Allocatable:
289 | cpu: 2
290 | ephemeral-storage: 16390445849
291 | hugepages-2Mi: 0
292 | memory: 1936224Ki
293 | pods: 110
294 | System Info:
295 | Machine ID: d4ca037d392045e1814f59e5c9b51c1d
296 | System UUID: 3EE4C717-994B-4FF3-8025-11D5E5E822CD
297 | Boot ID: 6ca21b67-8cf1-430d-8a97-ddcc8dbc397b
298 | Kernel Version: 4.15.0
299 | OS Image: Buildroot 2018.05.3
300 | Operating System: linux
301 | Architecture: amd64
302 | Container Runtime Version: docker://18.9.6
303 | Kubelet Version: v1.15.0
304 | Kube-Proxy Version: v1.15.0
305 | Non-terminated Pods: (15 in total)
306 | Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
307 | --------- ---- ------------ ---------- --------------- ------------- ---
308 | default nginx-77cd46f788-bd5kk 0 (0%) 0 (0%) 0 (0%) 0 (0%) 23h
309 | kube-system coredns-5c98db65d4-5cnpp 100m (5%) 0 (0%) 70Mi (3%) 170Mi (8%) 27h
310 | kube-system coredns-5c98db65d4-brqbq 100m (5%) 0 (0%) 70Mi (3%) 170Mi (8%) 27h
311 | kube-system default-http-backend-59f7ff8999-nnzvc 20m (1%) 20m (1%) 30Mi (1%) 30Mi (1%) 27h
312 | kube-system etcd-minikube 0 (0%) 0 (0%) 0 (0%) 0 (0%) 27h
313 | kube-system freshpod-v6z22 0 (0%) 0 (0%) 0 (0%) 0 (0%) 27h
314 | kube-system heapster-4d8gm 0 (0%) 0 (0%) 0 (0%) 0 (0%) 27h
315 | kube-system influxdb-grafana-9v876 0 (0%) 0 (0%) 0 (0%) 0 (0%) 27h
316 | kube-system kube-addon-manager-minikube 5m (0%) 0 (0%) 50Mi (2%) 0 (0%) 27h
317 | kube-system kube-apiserver-minikube 250m (12%) 0 (0%) 0 (0%) 0 (0%) 27h
318 | kube-system kube-controller-manager-minikube 200m (10%) 0 (0%) 0 (0%) 0 (0%) 25m
319 | kube-system kube-proxy-726vx 0 (0%) 0 (0%) 0 (0%) 0 (0%) 27h
320 | kube-system kube-scheduler-minikube 100m (5%) 0 (0%) 0 (0%) 0 (0%) 27h
321 | kube-system metrics-server-84bb785897-x6rz6 0 (0%) 0 (0%) 0 (0%) 0 (0%) 27h
322 | kube-system nginx-ingress-controller-7b465d9cf8-rv9k5 0 (0%) 0 (0%) 0 (0%) 0 (0%) 27h
323 | Allocated resources:
324 | (Total limits may be over 100 percent, i.e., overcommitted.)
325 | Resource Requests Limits
326 | -------- -------- ------
327 | cpu 775m (38%) 20m (1%)
328 | memory 220Mi (11%) 370Mi (19%)
329 | ephemeral-storage 0 (0%) 0 (0%)
330 | Events:
331 | Type Reason Age From Message
332 | ---- ------ ---- ---- -------
333 | Normal Starting 19h kubelet, minikube Starting kubelet.
334 | Normal NodeHasSufficientMemory 19h (x8 over 19h) kubelet, minikube Node minikube status is now: NodeHasSufficientMemory
335 | Normal NodeHasNoDiskPressure 19h (x8 over 19h) kubelet, minikube Node minikube status is now: NodeHasNoDiskPressure
336 | Normal NodeHasSufficientPID 19h (x7 over 19h) kubelet, minikube Node minikube status is now: NodeHasSufficientPID
337 | Normal NodeAllocatableEnforced 19h kubelet, minikube Updated Node Allocatable limit across pods
338 | Normal Starting 19h kube-proxy, minikube Starting kube-proxy.
339 | Normal NodeAllocatableEnforced 26m kubelet, minikube Updated Node Allocatable limit across pods
340 | Normal Starting 26m kubelet, minikube Starting kubelet.
341 | Normal NodeHasNoDiskPressure 26m (x8 over 26m) kubelet, minikube Node minikube status is now: NodeHasNoDiskPressure
342 | Normal NodeHasSufficientPID 26m (x7 over 26m) kubelet, minikube Node minikube status is now: NodeHasSufficientPID
343 | Normal NodeHasSufficientMemory 26m (x8 over 26m) kubelet, minikube Node minikube status is now: NodeHasSufficientMemory
344 | Normal Starting 25m kube-proxy, minikube Starting kube-proxy.
345 | Normal NodeNotSchedulable 3m54s kubelet, minikube Node minikube status is now: NodeNotSchedulable
346 | ```
347 |
348 | ## Readings
349 |
350 | * [kubernetes nodes](https://kubernetes.io/docs/concepts/architecture/nodes/)
351 |
352 | # Kubernetes Namespace
353 |
354 | Kubernetes namespace 是用来构建虚拟的资源池;使用 kubernetes namespace,管理员可以将 kubernetes
355 | 划分成多个虚拟的区域,不同的项目或者团队可以使用不同的 namespace,达到了共享 kubernetes 集群资源的目的。此外,
356 | namespace 也被用来划分命名空间,即不同 namespace 里的资源可以取相同的名字,相同 namespace 内的资源不能重名。
357 |
358 | ## Namespaces
359 |
360 | 通过 `kubectl create -f`,我们可以轻松地创建一个 namespace:
361 |
362 | ```
363 | $ kubectl create -f resources/ns.yaml
364 | namespace "tutorial" created
365 | ```
366 |
367 | 然后通过 `kubectl get ns`,可以看到刚才创建的 namespace
368 |
369 | ```
370 | $ kubectl get ns
371 | NAME STATUS AGE
372 | default Active 27h
373 | kube-node-lease Active 27h
374 | kube-public Active 27h
375 | kube-system Active 27h
376 | tutorial Active 7s
377 | ```
378 |
379 | 这里 `ns` 是 `namespace` 的缩写。输出内容中的 `default`, `kube-node-lease`, `kube-public` 和 `kube-system`,都是 kubernetes
380 | 默认创建的 namespace,用来放置系统相关的资源。
381 |
382 | ```sh
383 | $ kubectl describe ns tutorial
384 | Name: tutorial
385 | Labels:
386 | Annotations:
387 | Status: Active
388 |
389 | No resource quota.
390 |
391 | No resource limits.
392 | ```
393 |
394 | ## Readings
395 |
396 | * [kubernetes namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
397 | * [namespace walkthrough](https://kubernetes.io/docs/tasks/administer-cluster/namespaces-walkthrough/)
398 |
399 | # Kubernetes Pod & Deployment
400 |
401 | 当我们有一个 kubernetes 集群之后,可以开始部署应用了。在 kubernetes 的世界里,Pod 是运行应用的载体。
402 | Pod 是由多个容器组成、是 kubernetes 的最小调度单元、Pod 共享底层资源、由 kubernetes 来管理生命周期。然而,一般情况下,我们并不直接创建 Pod,而是通过 Deployment 来创建 Pod,由 Deployment 来负责创建、更新、维护其所管理的所有 Pods。
403 |
404 | 一旦我们通过 Deployment 创建 Pod,会有一个 Deployment 控制器不断监控所有 Pod 的状态。例如,如果 Pod
405 | 运行的机器宕机了,那么 Deployment 控制器会在另一台机器上重新启动一个 Pod。接下来,我们将部署一个应用,部署之后,集群将会达到下图所示的状态。
406 |
407 | 
408 | Image source: kubernetes guide
409 |
410 | 这里六边形方框代表一个 kubernetes 节点,正方体代表一个 Pod。后面,我们将通过 kubectl 来管理应用。
411 |
412 | ## Create Deployment
413 |
414 | 我们可以通过 yaml 文件创建 Deployment,从而创建应用。
415 |
416 | ```
417 | $ kubectl apply -f resources/deployment_nginx.yaml -n tutorial
418 | deployment.apps/nginx-deployment created
419 | ```
420 |
421 | 执行该命令之后,kubernetes 在集群中寻找一台满足需求的机器运行节点,然后该节点上的 agent 启动该应用。
422 |
423 | ## Get Deployment
424 |
425 | 创建好后,我们可以通过 `kubectl get deployment` 来查看刚刚创建的 Deployment:
426 |
427 | ```
428 | $ kubectl get deployment -n tutorial
429 | NAME READY UP-TO-DATE AVAILABLE AGE
430 | nginx 1/1 1 1 67s
431 | ```
432 |
433 | 从输出可以看出,我们请求创建一个 Pod (replica),kubernetes 已经帮我们成功创建了一个。
434 |
435 | ## Get Pods
436 |
437 | 上面我们讲到,真正运行应用的载体是 Pod,Deployment 是用来管理 Pod 的资源(比如重启失败的 Pod),我们可以通过
438 | `kubectl get pods` 来查看当前创建的 Pod。
439 |
440 | ```
441 | $ kubectl get pods -n tutorial
442 | NAME READY STATUS RESTARTS AGE
443 | nginx-646b46d648-hbwg2 1/1 Running 0 101s
444 | ```
445 |
446 | 可以看到,现在有一个 Pod 在运行中;我们可以通过 `kubectl get pods -o wide` 来查看 Pod 运行的主机,或者通过 `kubectl describe pods nginx-77cd46f788-bd5kk` 来查看 Pod 更加详细的信息(describe
447 | 中包含非常多的信息,我们将在后面介绍)。
448 |
449 | ```
450 | $ kubectl get pods -n tutorial -o wide
451 | NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
452 | nginx-646b46d648-hbwg2 1/1 Running 0 2m23s 172.17.0.11 minikube
453 | ```
454 |
455 | ## Get Pod Logs
456 |
457 | 当我们部署要应用之后,可以通过 `kubectl logs ` 和 `kubectl exec ` 与 Pod 交互。
458 |
459 | ```
460 | $ kubectl logs nginx-646b46d648-hbwg2 -n tutorial
461 | ```
462 |
463 | 由于没有任何请求,nginx pod 日志暂时为空。现在我们尝试访问 nginx pod。由于 `minikube` 本身是运行在虚拟机中,因此我们需要登录虚拟机访问 nginx pod (nginx pod ip: 172.17.0.11)。
464 |
465 | ```
466 | $ minikube ssh
467 | _ _
468 | _ _ ( ) ( )
469 | ___ ___ (_) ___ (_)| |/') _ _ | |_ __
470 | /' _ ` _ `\| |/' _ `\| || , < ( ) ( )| '_`\ /'__`\
471 | | ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )( ___/
472 | (_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)
473 |
474 | # in minikube vm
475 | $ curl 172.17.0.11
476 |
477 |
478 | ...
479 |
480 | ```
481 |
482 | 此时再查看 nginx,可以看到 nginx 的访问日志。
483 |
484 | ```
485 | $ kubectl logs nginx-3035859230-d2sfd -n tutorial
486 | 172.17.0.1 - - [28/Jun/2019:07:03:09 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.61.1" "-"
487 | ```
488 |
489 | ## Execute command in Pod
490 |
491 | 有时候,我们需要在 Pod 中执行命令,可以通过 `kubectl exec`:
492 |
493 | ```
494 | $ kubectl exec nginx-646b46d648-hbwg2 -n tutorial -- ls -l
495 | total 64
496 | drwxr-xr-x 2 root root 4096 Dec 4 2015 bin
497 | drwxr-xr-x 2 root root 4096 Aug 26 2015 boot
498 | drwxr-xr-x 5 root root 360 Jun 28 06:57 dev
499 | drwxr-xr-x 1 root root 4096 Jun 28 06:57 etc
500 | drwxr-xr-x 2 root root 4096 Aug 26 2015 home
501 | drwxr-xr-x 9 root root 4096 Nov 27 2014 lib
502 | drwxr-xr-x 2 root root 4096 Dec 4 2015 lib64
503 | drwxr-xr-x 2 root root 4096 Dec 4 2015 media
504 | drwxr-xr-x 2 root root 4096 Dec 4 2015 mnt
505 | drwxr-xr-x 2 root root 4096 Dec 4 2015 opt
506 | dr-xr-xr-x 226 root root 0 Jun 28 06:57 proc
507 | drwx------ 2 root root 4096 Dec 4 2015 root
508 | drwxr-xr-x 1 root root 4096 Jun 28 06:57 run
509 | drwxr-xr-x 2 root root 4096 Dec 4 2015 sbin
510 | drwxr-xr-x 2 root root 4096 Dec 4 2015 srv
511 | dr-xr-xr-x 12 root root 0 Jun 28 06:56 sys
512 | drwxrwxrwt 1 root root 4096 Dec 5 2015 tmp
513 | drwxr-xr-x 1 root root 4096 Dec 5 2015 usr
514 | drwxr-xr-x 1 root root 4096 Dec 5 2015 var
515 | ```
516 |
517 | 注意,我们通过双横线(“--”)区分本地终端命令和容器中执行的命令;当执行的命令只有一个单词的时候,可以省略。如果容器中有 `shell`,我们也可以启动一个远程终端:
518 |
519 | ```
520 | $ kubectl exec -it nginx-646b46d648-hbwg2 -n tutorial bash
521 | root@nginx-646b46d648-hbwg2:/# ls -l
522 | total 64
523 | drwxr-xr-x 2 root root 4096 Dec 4 2015 bin
524 | drwxr-xr-x 2 root root 4096 Aug 26 2015 boot
525 | drwxr-xr-x 5 root root 360 Jun 28 06:57 dev
526 | drwxr-xr-x 1 root root 4096 Jun 28 06:57 etc
527 | drwxr-xr-x 2 root root 4096 Aug 26 2015 home
528 | drwxr-xr-x 9 root root 4096 Nov 27 2014 lib
529 | drwxr-xr-x 2 root root 4096 Dec 4 2015 lib64
530 | drwxr-xr-x 2 root root 4096 Dec 4 2015 media
531 | drwxr-xr-x 2 root root 4096 Dec 4 2015 mnt
532 | drwxr-xr-x 2 root root 4096 Dec 4 2015 opt
533 | dr-xr-xr-x 226 root root 0 Jun 28 06:57 proc
534 | drwx------ 2 root root 4096 Dec 4 2015 root
535 | drwxr-xr-x 1 root root 4096 Jun 28 06:57 run
536 | drwxr-xr-x 2 root root 4096 Dec 4 2015 sbin
537 | drwxr-xr-x 2 root root 4096 Dec 4 2015 srv
538 | dr-xr-xr-x 12 root root 0 Jun 28 06:56 sys
539 | drwxrwxrwt 1 root root 4096 Dec 5 2015 tmp
540 | drwxr-xr-x 1 root root 4096 Dec 5 2015 usr
541 | drwxr-xr-x 1 root root 4096 Dec 5 2015 var
542 | ```
543 |
544 | 使用 `ctrl + d` 可以退出远程终端。
545 |
546 | ## Readings
547 |
548 | * [kubernetes pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/)
549 |
550 | # Kubernetes Service
551 |
552 | 接下来我们通过一连串的命令学习 kubernetes service。kubernetes service 有以下几个作用:
553 |
554 | * 提供固定的 IP。由于 Pod 可以随时启停,Pod IP 可能随时都会变化,例如上面 nginx pod 重启之后 IP
555 | 可能不再是 172.17.0.11。Service 为 Pods 提供的固定 IP,其他服务可以通过 Service IP 找到提供服务的
556 | Pods。
557 | * 提供负载均衡。Service 由多个 Pods 组成,kubernetes 对组成 Service 的 Pods 提供的负载均衡方案,例如随机访问、基于 Client IP 的 session affinity。
558 | * 服务发现。集群中其他服务可以通过 Service 名字访问后端服务(DNS),也可以通过环境变量访问。
559 |
560 | 下图是 kubernetes Pods, Service 的典型关系。下图有两个 Deployment: A 和 B。其中 Deployment A
561 | 创建了一个 Pods(黄色),Deployment B 创建了三个 Pod(绿色)。我们可以创建两个 Service: A 和 B。
562 | Service A 管理由 Deployment A 创建的 Pods,Service B 管理 Deployment B 创建的 Pods。可以看到,
563 | Service A 和 Service B 都有自己独立的 IP。无论他们所管理的容器如何变化, Service 的 IP 都不会变化。
564 |
565 | 
566 | Image source: kubernetes guide
567 |
568 | ## Create service
569 |
570 | 与其他资源相同,我们可以通过 `kubectl create -f` 加文件名创建 Service。但类似 Deployment,kubernetes
571 | 提供了快捷命令让我们能快速创建 Service。
572 |
573 | ```
574 | $ kubectl expose deployment nginx --port 80 -n tutorial
575 | service "nginx" exposed
576 | ```
577 |
578 | ## Get service
579 |
580 | 通过 `kubectl get service` 命令可以查看 service 的详细信息:
581 |
582 | ```
583 | $ kubectl get svc nginx -n tutorial
584 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
585 | nginx ClusterIP 10.96.6.136 80/TCP 15s
586 | ```
587 |
588 | 可以看到,Service 具有一个固定的 IP 10.96.6.136。同样,通过 describe 可以看到更多详细的信息:
589 |
590 | ```
591 | $ kubectl describe svc nginx -n tutorial
592 | Name: nginx
593 | Namespace: tutorial
594 | Labels: run=nginx
595 | Annotations:
596 | Selector: run=nginx
597 | Type: ClusterIP
598 | IP: 10.96.6.136
599 | Port: 80/TCP
600 | TargetPort: 80/TCP
601 | Endpoints: 172.17.0.11:80
602 | Session Affinity: None
603 | Events:
604 | ```
605 |
606 | 其中,Endpoint 表明 Service 所选中的 PodIP:PodPort。我们可以查看 Pod 信息来验证:
607 |
608 | ```
609 | $ kubectl get pods -o wide -n tutorial
610 | NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
611 | nginx-646b46d648-hbwg2 1/1 Running 0 14m 172.17.0.11 minikube
612 | ```
613 |
614 | ## Query service
615 |
616 | 创建 Service 后,我们可以在主机上直接访问该 Service。下面两条命令实际上访问的都是同一个后端。第一个命令通过 Service IP 访问,第二个命令通过 Pod IP 访问。
617 |
618 | 通过 Service IP 访问:
619 |
620 | ```
621 | $ minikube ssh
622 | $ curl 10.96.6.136
623 |
624 |
625 | ...
626 |
627 | ```
628 |
629 | 通过 Pod IP 访问:
630 |
631 | ```
632 | $ minikube ssh
633 | $ curl 172.17.0.11
634 |
635 |
636 | ...
637 |
638 | ```
639 |
640 | 上面的命令创建了一个名为 nginx 的 Service,并使用 80 作为服务端口。这里,我们的 nginx 容器监听的是容器的 80 端口,该端口是 Pod IP 所监听的端口;我们可以在 Service 上使用不同的端口。例如,若我们想暴露的服务端口是 8080 端口,需要使用 port 和 targetPort 选项。
641 |
642 | 首先,删除已经创建的 Service:
643 |
644 | ```
645 | $ kubectl delete svc nginx -n tutorial
646 | service "nginx" deleted
647 | ```
648 |
649 | 之后,创建 Service:
650 |
651 | ```
652 | $ kubectl expose deployment nginx --port 8080 --target-port 80 -n tutorial
653 | service "nginx" exposed
654 | ```
655 |
656 | 尝试用 8080 端口访问服务
657 |
658 | ```
659 | $ kubectl get svc nginx -n tutorial
660 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
661 | nginx ClusterIP 10.98.125.20 8080/TCP 6s
662 |
663 | $ minikube ssh
664 | $ curl 10.98.125.20:8080
665 |
666 |
667 | ...
668 |
669 | ```
670 |
671 | ## NodePort service
672 |
673 | 上述创建的 Service 只能被集群内部的节点和 Pod 访问,并不能被外部访问。我们可以通过两种方式暴露服务:`NodePort` 和 `LoadBalancer`。`NodePort` 通过在每个节点打开一个端口对外提供服务,`LoadBalancer` 通过创建一个外部负载均衡器(例如公有云负载均衡器)来对外提供服务。这里我们尝试使用 `NodePort`。
674 |
675 | 首先,删除已有的 Service:
676 |
677 | ```
678 | $ kubectl delete svc nginx -n tutorial
679 | service "nginx" deleted
680 | ```
681 |
682 | 通过 NodePort 暴露服务,注意这里使用了 `--type NodePort`:
683 |
684 | ```
685 | $ kubectl expose deployment nginx --port 80 --type NodePort -n tutorial
686 | service "nginx" exposed
687 | ```
688 |
689 | 查看 Service 的细节:
690 |
691 | ```
692 | $ kubectl get svc nginx -n tutorial
693 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
694 | nginx NodePort 10.107.97.57 80:32542/TCP 5s
695 | ```
696 |
697 | ```
698 | $ kubectl describe svc nginx -n tutorial
699 | Name: nginx
700 | Namespace: tutorial
701 | Labels: run=nginx
702 | Annotations:
703 | Selector: run=nginx
704 | Type: NodePort
705 | IP: 10.107.97.57
706 | Port: 80/TCP
707 | TargetPort: 80/TCP
708 | NodePort: 32542/TCP
709 | Endpoints: 172.17.0.11:80
710 | Session Affinity: None
711 | External Traffic Policy: Cluster
712 | Events:
713 | ```
714 |
715 | 从以上输出可以看到,nginx 服务打开了节点的 32542 端口(每个节点),我们可以通过 `NodeIP:NodePort` 访问服务。
716 |
717 | ```
718 | $ curl $(minikube ip):32542
719 |
720 |
721 | ...
722 |
723 | ```
724 |
725 | ## Readings
726 |
727 | * [kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). Please read as much as you can, we'll come back to service again.
728 | * [run application with service](https://kubernetes.io/docs/tasks/access-application-cluster/connecting-frontend-backend/).
729 | * [ports in kubernetes](https://speakerdeck.com/thockin/kubernetes-a-very-brief-explanation-of-ports)
730 |
731 | # Kubernetes Label
732 |
733 | Service 通过 selector & label 来选取它所管理的 Pod,同样 Deployment 也是通过 selector & label
734 | 选取它所管理的 Pod。因为我们是通过 Deployment 创建的 Pod,因此 Deployment 的 selector 一定是匹配
735 | Pod 的 label。如果我们想让 Service 选择与 Deployment 相同的 Pods,我们需要将 Service 的 selector
736 | 设为与 Deployment 相同。在上面的实验中,我们使用 `kubectl expose deployment nginx` 的时候,kubernetes
737 | 默认将 Service 的 selector 设置成与 Deployment 相同的 selector。下图对 label 做了详细的标注。
738 |
739 | 
740 | Image source: kubernetes guide
741 |
742 | 由上图可以看出:
743 |
744 | | Resource | selector |
745 | | ------------------------------ | -------- |
746 | | Deployment A, Service A, Pod A | app=A |
747 | | Deployment B, Service B, Pod B | app=B |
748 |
749 | Label 可以在创建时添加,也可以在运行时添加或修改。在运行时修改会影响集群的状态,因为现有的 selector & label
750 | 结构会被改变。
751 |
752 | ## View selector & label
753 |
754 | 从下面的输出可以看到,上述创建的 Deployment 和 Service 的 Selector 都是 `run=nginx`。Pod 具有 Label
755 | `pod-template-hash=646b46d648,run=nginx`,因此他们都选中了 `nginx-646b46d648-hbwg2` 这个 Pod (只要
756 | Pod label 的子集满足即可;这里的 `pod-template-hash=646b46d648` Label 是 kubernetes 自动创建)。
757 |
758 | ```
759 | $ kubectl describe deployment nginx -n tutorial
760 | Name: nginx
761 | Namespace: tutorial
762 | CreationTimestamp: Fri, 28 Jun 2019 14:56:58 +0800
763 | Labels: run=nginx
764 | Annotations: deployment.kubernetes.io/revision: 1
765 | Selector: run=nginx
766 | ...
767 | ```
768 |
769 | ```
770 | $ kubectl describe svc nginx -n tutorial
771 | Name: nginx
772 | Namespace: tutorial
773 | Labels: run=nginx
774 | Annotations:
775 | Selector: run=nginx
776 | ...
777 | ```
778 |
779 | ```
780 | $ kubectl describe pods nginx-646b46d648-hbwg2 -n tutorial
781 | Name: nginx-646b46d648-hbwg2
782 | Namespace: tutorial
783 | Priority: 0
784 | Node: minikube/10.0.2.15
785 | Start Time: Fri, 28 Jun 2019 14:56:59 +0800
786 | Labels: pod-template-hash=646b46d648
787 | run=nginx
788 | ```
789 |
790 | ## Label operations
791 |
792 | kubectl 支持对资源的 label 进行管理,比如我们可以通过 -l 选项查看仅具有某个 label 的资源。
793 |
794 | ```
795 | $ kubectl get pods -l run=nginx -n tutorial
796 | NAME READY STATUS RESTARTS AGE
797 | nginx-646b46d648-hbwg2 1/1 Running 0 26m
798 | ```
799 |
800 | ```
801 | $ kubectl get svc -l run=nginx -n tutorial
802 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
803 | nginx NodePort 10.107.97.57 80:32542/TCP 7m38s
804 | ```
805 |
806 | 当没有任何资源满足 label 时,输出为空:
807 |
808 | ```
809 | $ kubectl get svc -l run=apache -n tutorial
810 | No resources found.
811 | ```
812 |
813 | kubectl 支持对资源的 label 进行操作,如下所示:
814 |
815 | ```
816 | $ kubectl get pods -n tutorial
817 | NAME READY STATUS RESTARTS AGE
818 | nginx-646b46d648-hbwg2 1/1 Running 0 26m
819 |
820 | $ kubectl label pod nginx-646b46d648-hbwg2 app=v1 -n tutorial
821 | pod/nginx-646b46d648-hbwg2 labeled
822 |
823 | $ kubectl describe pods nginx-646b46d648-hbwg2 -n tutorial
824 | Name: nginx-646b46d648-hbwg2
825 | Namespace: tutorial
826 | Priority: 0
827 | Node: minikube/10.0.2.15
828 | Start Time: Fri, 28 Jun 2019 14:56:59 +0800
829 | Labels: app=v1
830 | pod-template-hash=646b46d648
831 | run=nginx
832 | Annotations:
833 | Status: Running
834 | IP: 172.17.0.11
835 | Controlled By: ReplicaSet/nginx-646b46d648
836 | ```
837 |
838 | 注意这里我们是对 Pod 添加了一个 label,并不会影响 Deployment 与 Pod 之间的关系。因为 Pod 保持 Label
839 | `run=nginx`,依然会被 Deployment 选中。
840 |
841 | ## Readings
842 |
843 | * [label and selector](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
844 |
845 | # Kubernetes Deployment Operations
846 |
847 | ## Scale up using kubectl
848 |
849 | 接下来我们将学习 kubernetes Deployment 的另外两个操作:水平扩展应用和更新应用。下图中,Deployment A
850 | 有一个 Pod 在运行,Service A 管理该 Pod。
851 |
852 | 
853 | Image source: kubernetes guide
854 |
855 | 通过调整 Deployment 的副本数量,我们可以将 Pod 的数量调整到 4 个。与此同时,Service 会感知到同样 label 的
856 | Pod 被扩容到了 4 个,会将流量导到所有 Pod(而不是只有最开始的 Pod)。
857 |
858 | 
859 | Image source: kubernetes guide
860 |
861 | 首先创建 Deployment 和 Service(确保前面教程的 Deployment 和 Service 已经被删除):
862 |
863 | ```
864 | kubectl apply -f resources/deployment_nginx -n tutorial
865 | kubectl expose deployment nginx --port 80 --name=nginx -n tutorial
866 | ```
867 |
868 | 接下来,我们可以通过 `kubectl scale` 子命令将 Pod 数量扩容到四个:
869 |
870 | ```
871 | $ kubectl get deployments -n tutorial
872 | NAME READY UP-TO-DATE AVAILABLE AGE
873 | nginx 1/1 1 1 13s
874 |
875 | $ kubectl scale deployments nginx --replicas=4 -n tutorial
876 | deployment.extensions/nginx scaled
877 |
878 | $ kubectl get deployments -n tutorial
879 | NAME READY UP-TO-DATE AVAILABLE AGE
880 | nginx 4/4 4 4 49s
881 |
882 | $ kubectl get pods -n tutorial -o wide
883 | NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
884 | nginx-d6b94d6f6-lggxr 1/1 Running 0 28s 172.17.0.11 minikube
885 | nginx-d6b94d6f6-lkr8m 1/1 Running 0 59s 172.17.0.8 minikube
886 | nginx-d6b94d6f6-npntj 1/1 Running 0 28s 172.17.0.13 minikube
887 | nginx-d6b94d6f6-rh42k 1/1 Running 0 28s 172.17.0.12 minikube
888 | ```
889 |
890 | 可以看到目前有四个 Pods,其中 `AGE` 较小的是新生成的。
891 |
892 | ## View service
893 |
894 | 之前提到,Service 会感知到 Pods 的变化,在所有的 Pods 中负载均衡,我们可以通过 kubectl 查看。
895 |
896 | ```
897 | $ kubectl describe service nginx -n tutorial
898 | Name: nginx
899 | Namespace: tutorial
900 | Labels: run=nginx
901 | Annotations:
902 | Selector: run=nginx
903 | Type: ClusterIP
904 | IP: 10.103.221.162
905 | Port: 80/TCP
906 | TargetPort: 80/TCP
907 | Endpoints: 172.17.0.11:80,172.17.0.12:80,172.17.0.13:80 + 1 more...
908 | Session Affinity: None
909 | Events:
910 | ```
911 |
912 | Service nginx 已经将后端 Endpoints 扩容到所有的 4 个 Pods。
913 |
914 | ## Scale down using kubectl
915 |
916 | 我们也可以通过同样的命令缩容(kubectl scale)。Deployment 不会区分是扩容命令或是缩容命令,它只关心将实例的数量调整到指定的数量。
917 |
918 | ```
919 | $ kubectl scale deployments nginx --replicas=2 -n tutorial
920 | deployment.extensions/nginx scaled
921 |
922 | $ kubectl get pods -n tutorial
923 | NAME READY STATUS RESTARTS AGE
924 | nginx-d6b94d6f6-lkr8m 1/1 Running 0 4m58s
925 | nginx-d6b94d6f6-rh42k 1/1 Running 0 4m27s
926 | ```
927 |
928 | ## Update deployment
929 |
930 | 接下来,我们将了解 kubernetes 如何进行应用更新。见下图,我们目前有四个运行中的应用:
931 |
932 | 
933 | Image source: kubernetes guide
934 |
935 | 当我们更新容器镜像时,kubernetes 会启动一个新 Pod 并关闭一个老 Pod。下图中,紫色的 Pod 为 kubernetes
936 | 新创建的 Pod,淡绿色 Pod 为老 Pod。Service 会停止向老 Pod 导流。
937 |
938 | 
939 | Image source: kubernetes guide
940 |
941 | 第一个 Pod 更新成功后,Deployment 会更新第二个 Pod。如下图所示,紫色两个 Pod 为 Deployment 创建的新 Pod。
942 |
943 | 
944 | Image source: kubernetes guide
945 |
946 | 最后,Deployment 将所有的 Pod 都更新完毕。
947 |
948 | 
949 | Image source: kubernetes guide
950 |
951 | ## Update via setting image
952 |
953 | 接下来,我们通过命令行了解 kubernetes 更新应用的过程。
954 |
955 | ```
956 | $ kubectl set image deployments nginx nginx=cargo.caicloud.io/caicloud/nginx:1.9.3 -n tutorial
957 | deployment.extensions/nginx image updated
958 |
959 | $ kubectl get pods -n tutorial
960 | NAME READY STATUS RESTARTS AGE
961 | nginx-d6b94d6f6-lkr8m 0/1 Terminating 0 5m58s
962 | nginx-d6b94d6f6-rh42k 1/1 Running 0 5m27s
963 | nginx-86d4667764-gxwkb 1/1 Running 0 4s
964 | nginx-86d4667764-hr6r7 0/1 ContainerCreating 0 2s
965 | ```
966 |
967 | 过一段时间后,所有 Pod 都已经更新了:
968 |
969 | ```
970 | $ kubectl get pods -n tutorial
971 | NAME READY STATUS RESTARTS AGE
972 | nginx-86d4667764-gxwkb 1/1 Running 0 67s
973 | nginx-86d4667764-hr6r7 1/1 Running 0 65s
974 | ```
975 |
976 | 分析一下上述命令,`kubectl set image` 将 Deployment 中的 nginx 镜像版本改为 1.9.3;运行该命令之后,发现
977 | kubernetes 删掉了一个现有的 Pod,然后重新启动了两个新的 Pod(我们可以从一串数字中看出,"86d4667764" 是新 Pod 的 Hash 值,"d6b94d6f6" 是老 Pod 的 Hash 值)。等待一段时间后再次查询 Pods,发现所有新的 Pods 已经上线。整个过程中,我们都可以尝试去访问 nginx 服务,注意其版本的变化。
978 |
979 | ```
980 | $ curl $(minikube ip):31658/version
981 |
982 | ...
983 |
nginx/1.9.3
984 |
985 | ```
986 |
987 | 其中 31658 是 Service 暴露的 NodePort 端口。
988 |
989 | ## Deployment rollout
990 |
991 | rollout 子命令可以用来查询部署的状态,以及回滚等操作。使用 `kubectl rollout status` 可以查询部署的状态。
992 |
993 | ```
994 | $ kubectl rollout status deployment nginx -n tutorial
995 | deployment "nginx" successfully rolled out
996 | ```
997 |
998 | 上面的状态说明之前部署的 Deployment 已经正常部署了。如果我们想要回滚到之前的版本,可以使用
999 | `kubectl rollout undo` 命令。
1000 |
1001 | 首先,当前 nginx 处于 1.9.3 版本:
1002 |
1003 | ```
1004 | $ curl $(minikube ip):31658/version
1005 |
1006 | ...
1007 |
nginx/1.9.3
1008 |
1009 |