diff --git a/.gitignore b/.gitignore index dbe9c82b3610ccd58d1c681848dcd322e500051e..b9c15c41ac84e63e43d9fd4050c4414a4c573d79 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -.vscode/ \ No newline at end of file +.vscode/ +node_modules/ +book.json +SUMMARY.md +_book/* diff --git a/README.md b/README.md index 5b6243ee41e26ddef5691569012ad5f869c9c0f0..5f6350ad8d7d0690d83a083dd2183fdbb03d7f0f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# kubernetes learning —— 从Docker到Kubernetes进阶 +# 从Docker到Kubernetes进阶 +从 Docker 入门一步步迁移到 Kubernetes 的进阶课程 ## 介绍 @@ -40,7 +41,3 @@ GitHub地址:[https://github.com/cnych/kubernetes-learning/tree/master/docs](h ![优点知识服务号](./docs/images/ydzs-qrcode.png) ![优点知识小程序](./docs/images/ydzs-xcx.png) -## 目录 - -TODO,整理中,部分可以通过[docs](https://github.com/cnych/kubernetes-learning/tree/master/docs)目录查看 - diff --git "a/docs/18.YAML \346\226\207\344\273\266.md" "b/docs/18.YAML \346\226\207\344\273\266.md" new file mode 100644 index 0000000000000000000000000000000000000000..bae5121fd9343db434cce38ef997fcfa4b69eae3 --- /dev/null +++ "b/docs/18.YAML \346\226\207\344\273\266.md" @@ -0,0 +1,277 @@ +# 18. YAML 文件 + +在前面的课程中,我们在安装 kubernetes 集群的时候使用了一些 YAML 文件来创建相关的资源,但是很多同学对 YAML 文件还是非常陌生。所以我们先来简单看一看 YAML 文件是如何工作的,并使用 YAML 文件来定义一个 kubernetes pod,然后再来定义一个 kubernetes deployment吧。 + +## YAML 基础 +它的基本语法规则如下: + +* 大小写敏感 +* 使用缩进表示层级关系 +* 缩进时不允许使用Tab键,只允许使用空格。 +* 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可 +* `#` 表示注释,从这个字符一直到行尾,都会被解析器忽略。 + +在我们的 kubernetes 中,你只需要两种结构类型就行了: + +* Lists +* Maps + +也就是说,你可能会遇到 Lists 的 Maps 和 Maps 的 Lists,等等。不过不用担心,你只要掌握了这两种结构也就可以了,其他更加复杂的我们暂不讨论。 + +### Maps +首先我们来看看 Maps,我们都知道 Map 是字典,就是一个`key:value`的键值对,Maps 可以让我们更加方便的去书写配置信息,例如: +```yaml +--- +apiVersion: v1 +kind: Pod +``` +第一行的`---`是分隔符,是可选的,在单一文件中,可用连续三个连字号`---`区分多个文件。这里我们可以看到,我们有两个键:`kind` 和 `apiVersion`,他们对应的值分别是:v1 和Pod。上面的 YAML 文件转换成 JSON 格式的话,你肯定就容易明白了: +```json +{ + "apiVersion": "v1", + "kind": "pod" +} +``` + +我们在创建一个相对复杂一点的 YAML 文件,创建一个 KEY 对应的值不是字符串而是一个 Maps: +```yaml +--- +apiVersion: v1 +kind: Pod +metadata: + name: kube100-site + labels: + app: web +``` + +上面的 YAML 文件,metadata 这个 KEY 对应的值就是一个 Maps 了,而且嵌套的 labels 这个 KEY 的值又是一个 Map,你可以根据你自己的情况进行多层嵌套。 + +上面我们也提到了 YAML 文件的语法规则,YAML 处理器是根据行缩进来知道内容之间的嗯关联性的。比如我们上面的 YAML 文件,**我用了两个空格作为缩进,空格的数量并不重要,但是你得保持一致,并且至少要求一个空格**(什么意思?就是你别一会缩进两个空格,一会缩进4个空格)。 + +我们可以看到 name 和 labels 是相同级别的缩进,所以 YAML 处理器就知道了他们属于同一个 MAP,而 app 是 labels 的值是因为 app 的缩进更大。 + +> 注意:在 YAML 文件中绝对不要使用 tab 键。 + +同样的,我们可以将上面的 YAML 文件转换成 JSON 文件: +```json +{ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "kube100-site", + "labels": { + "app": "web" + } + } +} +``` + +或许你对上面的 JSON 文件更熟悉,但是你不得不承认 YAML 文件的语义化程度更高吧? + +### Lists +Lists 就是列表,说白了就是数组,在 YAML 文件中我们可以这样定义: +```yaml +args + - Cat + - Dog + - Fish +``` + +你可以有任何数量的项在列表中,每个项的定义以破折号(-)开头的,与父元素直接可以缩进一个空格。对应的 JSON 格式如下: +```json +{ + "args": [ 'Cat', 'Dog', 'Fish' ] +} +``` + +当然,list 的子项也可以是 Maps,Maps 的子项也可以是list如下所示: +```yaml +--- +apiVersion: v1 +kind: Pod +metadata: + name: kube100-site + labels: + app: web +spec: + containers: + - name: front-end + image: nginx + ports: + - containerPort: 80 + - name: flaskapp-demo + image: jcdemo/flaskapp + ports: + - containerPort: 5000 +``` + +比如这个 YAML 文件,我们定义了一个叫 containers 的 List 对象,每个子项都由 name、image、ports 组成,每个 ports 都有一个 key 为 containerPort 的 Map 组成,同样的,我们可以转成如下 JSON 格式文件: +```json +{ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": "kube100-site", + "labels": { + "app": web" + } + }, + "spec": { + "containers": [{ + "name": "front-end", + "image": "nginx", + "ports": [{ + "containerPort": "80" + }] + }, { + "name": "flaskapp-demo", + "image": "jcdemo/flaskapp", + "ports": [{ + "containerPort": "5000" + }] + }] + } +} +``` + +是不是觉得用 JSON 格式的话文件明显比 YAML 文件更复杂了呢? + +### 使用 YAML 创建 Pod +现在我们已经对 YAML 文件有了大概的了解了,我相信你应该没有之前那么懵逼了吧?我们还是来使用 YAML 文件来创建一个 Deployment 吧。 + +API 说明: [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/) + +#### 创建 Pod +```yaml +--- +apiVersion: v1 +kind: Pod +metadata: + name: kube100-site + labels: + app: web +spec: + containers: + - name: front-end + image: nginx + ports: + - containerPort: 80 + - name: flaskapp-demo + image: jcdemo/flaskapp + ports: + - containerPort: 5000 +``` +这是我们上面定义的一个普通的 POD 文件,我们先来简单分析下文件内容: + +* apiVersion,这里它的值是 v1,这个版本号需要根据我们安装的 kubernetes 版本和资源类型进行变化的,记住不是写死的 +* kind,这里我们创建的是一个 Pod,当然根据你的实际情况,这里资源类型可以是 Deployment、Job、Ingress、Service 等待。 +* metadata:包含了我们定义的 Pod 的一些 meta 信息,比如名称、namespace、标签等等信息。 +* spec:包括一些 containers,storage,volumes,或者其他 Kubernetes 需要知道的参数,以及诸如是否在容器失败时重新启动容器的属性。你可以在特定 Kubernetes API 找到完整的 Kubernetes Pod 的属性。 + +让我们来看一个典型的容器的定义: +```yaml +…spec: + containers: + - name: front-end + image: nginx + ports: + - containerPort: 80 +… +``` +在这个例子中,这是一个简单的最小定义:一个名字(front-end),基于 nginx 的镜像,以及容器 将会监听的一个端口(80)。在这些当中,只有名字是非常需要的,你也可以指定一个更加复杂的属性,例如在容器启动时运行的命令,应使用的参数,工作目录,或每次实例化时是否拉取映像的新副本。以下是一些容器可选的设置属性: + +* name +* image +* command +* args +* workingDir +* ports +* env +* resources +* volumeMounts +* livenessProbe +* readinessProbe +* livecycle +* terminationMessagePath +* imagePullPolicy +* securityContext +* stdin +* stdinOnce +* tty + +明白了 POD 的定义后,我们将上面创建 POD 的 YAML 文件保存成 pod.yaml,然后使用`kubectl`创建 POD: +```shell +$ kubectl create -f pod.yaml +pod "kube100-site" created +``` + +然后我们就可以使用我们前面比较熟悉的 kubectl 命令来查看 POD 的状态了: +```shell +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +kube100-site 2/2 Running 0 1m +``` + +到这里我们的 POD 就创建成功了,如果你在创建过程中有任何问题,我们同样可以使用前面的kubectl describe 进行排查。我们先删除上面创建的 POD: +``` +$ kubectl delete -f pod.yaml +pod "kube100-site" deleted +``` + +#### 创建 Deployment +现在我们可以来创建一个真正的 Deployment。在上面的例子中,我们只是单纯的创建了一个 POD 实例,但是如果这个 POD 出现了故障的话,我们的服务也就挂掉了,所以 kubernetes 提供了一个`Deployment`的概念,可以让 kubernetes 去管理一组 POD 的副本,也就是副本集,这样就可以保证一定数量的副本一直可用的,不会因为一个 POD 挂掉导致整个服务挂掉。我们可以这样定义一个 Deployment: +```yaml +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: kube100-site +spec: + replicas: 2 +``` + +注意这里的`apiVersion`对应的值是`extensions/v1beta1`,当然 kind 要指定为 Deployment,因为这就是我们需要的,然后我们可以指定一些 meta 信息,比如名字,或者标签之类的。最后,最重要的是`spec`配置选项,这里我们定义需要两个副本,当然还有很多可以设置的属性,比如一个 Pod 在没有任何错误变成准备的情况下必须达到的最小秒数。 +我们可以在[Kubernetes v1beta1 API](https://kubernetes.io/docs/api-reference/extensions/v1beta1/definitions/#_v1beta1_deployment)参考中找到一个完整的 Depolyment 可指定的参数列表。 +现在我们来定义一个完整的 Deployment 的 YAML 文件: +```yaml +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: kube100-site +spec: + replicas: 2 + template: + metadata: + labels: + app: web + spec: + containers: + - name: front-end + image: nginx + ports: + - containerPort: 80 + - name: flaskapp-demo + image: jcdemo/flaskapp + ports: + - containerPort: 5000 +``` + +看起来是不是和我们上面的 pod.yaml 很类似啊,注意其中的 template,其实就是对 POD 对象的定义。将上面的 YAML 文件保存为 deployment.yaml,然后创建 Deployment: +```shell +$ kubectl create -f deployment.yaml +deployment "kube100-site" created +``` + +同样的,想要查看它的状态,我们可以检查 Deployment的列表: +```shell +$ kubectl get deployments +NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE +kube100-site 2 2 2 2 2m +``` +我们可以看到所有的 Pods 都已经正常运行了。 + +到这里我们就完成了使用 YAML 文件创建 Kubernetes Deployment 的过程,在了解了 YAML 文件的基础后,定义 YAML 文件其实已经很简单了,最主要的是要根据实际情况去定义 YAML 文件,所以查阅 Kubernetes 文档很重要。 + +> 可以使用[http://www.yamllint.com/](http://www.yamllint.com/)去检验 YAML 文件的合法性。 + diff --git "a/docs/19.\351\235\231\346\200\201 Pod.md" "b/docs/19.\351\235\231\346\200\201 Pod.md" new file mode 100644 index 0000000000000000000000000000000000000000..a2d0a4ebf2bd40ced94d9ce39b05d67f706ebdf6 --- /dev/null +++ "b/docs/19.\351\235\231\346\200\201 Pod.md" @@ -0,0 +1,100 @@ +# 静态 Pod +我们上节课给大家讲解了 YAML 文件的使用,也手动的创建了一个简单的 Pod,这节课开始我们就来深入的学习下我们的 Pod。在Kubernetes集群中除了我们经常使用到的普通的 Pod 外,还有一种特殊的 Pod,叫做`Static Pod`,就是我们说的静态 Pod,静态 Pod 有什么特殊的地方呢? + +静态 Pod 直接由特定节点上的`kubelet`进程来管理,不通过 master 节点上的`apiserver`。无法与我们常用的控制器`Deployment`或者`DaemonSet`进行关联,它由`kubelet`进程自己来监控,当`pod`崩溃时重启该`pod`,`kubelete`也无法对他们进行健康检查。静态 pod 始终绑定在某一个`kubelet`,并且始终运行在同一个节点上。 +`kubelet`会自动为每一个静态 pod 在 Kubernetes 的 apiserver 上创建一个镜像 Pod(Mirror Pod),因此我们可以在 apiserver 中查询到该 pod,但是不能通过 apiserver 进行控制(例如不能删除)。 + +创建静态 Pod 有两种方式:配置文件和 HTTP 两种方式 + +### 配置文件 +配置文件就是放在特定目录下的标准的 JSON 或 YAML 格式的 pod 定义文件。用`kubelet --pod-manifest-path=`来启动`kubelet`进程,kubelet 定期的去扫描这个目录,根据这个目录下出现或消失的 YAML/JSON 文件来创建或删除静态 pod。 + +比如我们在 node01 这个节点上用静态 pod 的方式来启动一个 nginx 的服务。我们登录到node01节点上面,可以通过下面命令找到kubelet对应的启动配置文件 +```shell +$ systemctl status kubelet +``` + +配置文件路径为: +```shell +$ /etc/systemd/system/kubelet.service.d/10-kubeadm.conf +``` + +打开这个文件我们可以看到其中有一条如下的环境变量配置: +`Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"` + +所以如果我们通过`kubeadm`的方式来安装的集群环境,对应的`kubelet`已经配置了我们的静态 Pod 文件的路径,那就是`/etc/kubernetes/manifests`,所以我们只需要在该目录下面创建一个标准的 Pod 的 JSON 或者 YAML 文件即可: + +如果你的 kubelet 启动参数中没有配置上面的`--pod-manifest-path`参数的话,那么添加上这个参数然后重启 kubelet 即可。 +```yaml +[root@ node01 ~] $ cat </etc/kubernetes/manifest/static-web.yaml +apiVersion: v1 +kind: Pod +metadata: + name: static-web + labels: + app: static +spec: + containers: + - name: web + image: nginx + ports: + - name: web + containerPort: 80 +EOF +``` + +### 通过 HTTP 创建静态 Pods +kubelet 周期地从`–manifest-url=`参数指定的地址下载文件,并且把它翻译成 JSON/YAML 格式的 pod 定义。此后的操作方式与`–pod-manifest-path=`相同,kubelet 会不时地重新下载该文件,当文件变化时对应地终止或启动静态 pod。 + +### 静态pods的动作行为 +kubelet 启动时,由`--pod-manifest-path= or --manifest-url=`参数指定的目录下定义的所有 pod 都会自动创建,例如,我们示例中的 static-web。(可能要花些时间拉取nginx 镜像,耐心等待…) +```shell +[root@node01 ~] $ docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-node1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c +``` + +现在我们通过`kubectl`工具可以看到这里创建了一个新的镜像 Pod: +```shell +[root@node01 ~] $ kubectl get pods +NAME READY STATUS RESTARTS AGE +static-web-my-node01 1/1 Running 0 2m +``` + +静态 pod 的标签会传递给镜像 Pod,可以用来过滤或筛选。 +需要注意的是,我们不能通过 API 服务器来删除静态 pod(例如,通过[kubectl](https://kubernetes.io/docs/user-guide/kubectl/)命令),kebelet 不会删除它。 +```shell +[root@node01 ~] $ kubectl delete pod static-web-my-node01 +[root@node01 ~] $ kubectl get pods +NAME READY STATUS RESTARTS AGE +static-web-my-node01 1/1 Running 0 12s +``` + +我们尝试手动终止容器,可以看到kubelet很快就会自动重启容器。 +```shell +[root@node01 ~] $ docker ps +CONTAINER ID IMAGE COMMAND CREATED ... +5b920cbaf8b1 nginx:latest "nginx -g 'daemon of 2 seconds ago ... +``` + +### 静态pods的动态增加和删除 +运行中的kubelet周期扫描配置的目录(我们这个例子中就是/etc/kubernetes/manifests)下文件的变化,当这个目录中有文件出现或消失时创建或删除pods。 +```shell +[root@node01 ~] $ mv /etc/kubernetes/manifests/static-web.yaml /tmp +[root@node01 ~] $ sleep 20 +[root@node01 ~] $ docker ps +// no nginx container is running +[root@node01 ~] $ mv /tmp/static-web.yaml /etc/kubernetes/manifests +[root@node01 ~] $ sleep 20 +[root@node01 ~] $ docker ps +CONTAINER ID IMAGE COMMAND CREATED ... +e7a62e3427f1 nginx:latest "nginx -g 'daemon of 27 seconds ago +``` + +其实我们用 kubeadm 安装的集群,master 节点上面的几个重要组件都是用静态 Pod 的方式运行的,我们登录到 master 节点上查看`/etc/kubernetes/manifests`目录: +```shell +[root@master ~]# ls /etc/kubernetes/manifests/ +etcd.yaml kube-apiserver.yaml kube-controller-manager.yaml kube-scheduler.yaml +``` + +现在明白了吧,这种方式也为我们将集群的一些组件容器化提供了可能,因为这些 Pod 都不会受到 apiserver 的控制,不然我们这里`kube-apiserver`怎么自己去控制自己呢?万一不小心把这个 Pod 删掉了呢?所以只能有`kubelet`自己来进行控制,这就是我们所说的静态 Pod。 diff --git a/docs/20.Pod Hook.md b/docs/20.Pod Hook.md new file mode 100644 index 0000000000000000000000000000000000000000..4036eec6b53ae062415db8ff93d3ebfb642475ad --- /dev/null +++ b/docs/20.Pod Hook.md @@ -0,0 +1,89 @@ +# Pod Hook + +我们知道`Pod`是`Kubernetes`集群中的最小单元,而 Pod 是有容器组组成的,所以在讨论 Pod 的生命周期的时候我们可以先来讨论下容器的生命周期。 + +实际上 Kubernetes 为我们的容器提供了生命周期钩子的,就是我们说的`Pod Hook`,Pod Hook 是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。我们可以同时为 Pod 中的所有容器都配置 hook。 + +Kubernetes 为我们提供了两种钩子函数: + +* PostStart:这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器`ENTRYPOINT`之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起, 容器将不能达到`running`状态。 +* PreStop:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起, Pod阶段将停留在`running`状态并且永不会达到`failed`状态。 + +如果`PostStart`或者`PreStop`钩子失败, 它会杀死容器。所以我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态。 + +另外我们有两种方式来实现上面的钩子函数: + +* Exec - 用于执行一段特定的命令,不过要注意的是该命令消耗的资源会被计入容器。 +* HTTP - 对容器上的特定的端点执行`HTTP`请求。 + + +### 示例1 环境准备 +以下示例中,定义了一个Nginx Pod,其中设置了`PostStart`钩子函数,即在容器创建成功后,写入一句话到`/usr/share/message`文件中。 +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: hook-demo1 +spec: + containers: + - name: hook-demo1 + image: nginx + lifecycle: + postStart: + exec: + command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] +``` + +### 示例2 优雅删除资源对象 +当用户请求删除含有 pod 的资源对象时(如Deployment等),K8S 为了让应用程序优雅关闭(即让应用程序完成正在处理的请求后,再关闭软件),K8S提供两种信息通知: + +* 默认:K8S 通知 node 执行`docker stop`命令,docker 会先向容器中`PID`为1的进程发送系统信号`SIGTERM`,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送`SIGKILL`的系统信号强行 kill 掉进程。 +* 使用 pod 生命周期(利用`PreStop`回调函数),它执行在发送终止信号之前。 + +默认所有的优雅退出时间都在30秒内。kubectl delete 命令支持 `--grace-period=`选项,这个选项允许用户用他们自己指定的值覆盖默认值。值'0'代表 强制删除 pod. 在 kubectl 1.5 及以上的版本里,执行强制删除时必须同时指定 `--force --grace-period=0`。 + +强制删除一个 pod 是从集群状态还有 etcd 里立刻删除这个 pod。 当 Pod 被强制删除时, api 服务器不会等待来自 Pod 所在节点上的 kubelet 的确认信息:pod 已经被终止。在 API 里 pod 会被立刻删除,在节点上, pods 被设置成立刻终止后,在强行杀掉前还会有一个很小的宽限期。 + +以下示例中,定义了一个Nginx Pod,其中设置了`PreStop`钩子函数,即在容器退出之前,优雅的关闭 Nginx: +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: hook-demo2 +spec: + containers: + - name: hook-demo2 + image: nginx + lifecycle: + preStop: + exec: + command: ["/usr/sbin/nginx","-s","quit"] + +--- +apiVersion: v1 +kind: Pod +metadata: + name: hook-demo2 + labels: + app: hook +spec: + containers: + - name: hook-demo2 + image: nginx + ports: + - name: webport + containerPort: 80 + volumeMounts: + - name: message + mountPath: /usr/share/ + lifecycle: + preStop: + exec: + command: ['/bin/sh', '-c', 'echo Hello from the preStop Handler > /usr/share/message'] + volumes: + - name: message + hostPath: + path: /tmp +``` + +另外`Hook`调用的日志没有暴露个给 Pod 的 event,所以只能通过`describe`命令来获取,如果有错误将可以看到`FailedPostStartHook`或`FailedPreStopHook`这样的 event。 diff --git "a/docs/21. \345\201\245\345\272\267\346\243\200\346\237\245.md" "b/docs/21.\345\201\245\345\272\267\346\243\200\346\237\245.md" similarity index 99% rename from "docs/21. \345\201\245\345\272\267\346\243\200\346\237\245.md" rename to "docs/21.\345\201\245\345\272\267\346\243\200\346\237\245.md" index 1761bf98214bf542376d3b3030b3d013e681269b..ecdd3e4721bb82111a8cb854c1edffbcf5eec8ce 100644 --- "a/docs/21. \345\201\245\345\272\267\346\243\200\346\237\245.md" +++ "b/docs/21.\345\201\245\345\272\267\346\243\200\346\237\245.md" @@ -1,3 +1,4 @@ + ## 21. 健康检查 上节课我们和大家一起学习了`Pod`中容器的生命周期的两个钩子函数,`PostStart`与`PreStop`,其中`PostStart`是在容器创建后立即执行的,而`PreStop`这个钩子函数则是在容器终止之前执行的。除了上面这两个钩子函数以外,还有一项配置会影响到容器的生命周期的,那就是健康检查的探针。 @@ -85,7 +86,7 @@ spec: 通常来说,任何大于200小于400的返回码都会认定是成功的返回码。其他返回码都会被认为是失败的返回码。 我们可以来查看下上面的`healthz`的实现: -```golang +```go http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { duration := time.Now().Sub(started) if duration.Seconds() > 10 { @@ -143,7 +144,7 @@ spec: 另外除了上面的`initialDelaySeconds`和`periodSeconds`属性外,探针还可以配置如下几个参数: - + * timeoutSeconds:探测超时时间,默认1秒,最小1秒。 * successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是 1,但是如果是`liveness`则必须是 1。最小值是 1。 * failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是 3,最小值是 1。 diff --git "a/docs/22. \345\210\235\345\247\213\345\214\226\345\256\271\345\231\250.md" "b/docs/22.\345\210\235\345\247\213\345\214\226\345\256\271\345\231\250.md" similarity index 100% rename from "docs/22. \345\210\235\345\247\213\345\214\226\345\256\271\345\231\250.md" rename to "docs/22.\345\210\235\345\247\213\345\214\226\345\256\271\345\231\250.md" diff --git "a/docs/23. \344\275\277\347\224\250RC(RS)\347\256\241\347\220\206Pod.md" "b/docs/23.\344\275\277\347\224\250RC\347\256\241\347\220\206Pod.md" similarity index 100% rename from "docs/23. \344\275\277\347\224\250RC(RS)\347\256\241\347\220\206Pod.md" rename to "docs/23.\344\275\277\347\224\250RC\347\256\241\347\220\206Pod.md" diff --git "a/docs/24. Deployment \344\275\277\347\224\250.md" "b/docs/24.Deployment \344\275\277\347\224\250.md" similarity index 100% rename from "docs/24. Deployment \344\275\277\347\224\250.md" rename to "docs/24.Deployment \344\275\277\347\224\250.md" diff --git "a/docs/25. Pod \346\260\264\345\271\263\350\207\252\345\212\250\344\274\270\347\274\251.md" "b/docs/25.Pod \346\260\264\345\271\263\350\207\252\345\212\250\344\274\270\347\274\251.md" similarity index 100% rename from "docs/25. Pod \346\260\264\345\271\263\350\207\252\345\212\250\344\274\270\347\274\251.md" rename to "docs/25.Pod \346\260\264\345\271\263\350\207\252\345\212\250\344\274\270\347\274\251.md" diff --git "a/docs/26. Job\344\270\216Cronjob \347\232\204\344\275\277\347\224\250.md" "b/docs/26.Job\344\270\216Cronjob \347\232\204\344\275\277\347\224\250.md" similarity index 100% rename from "docs/26. Job\344\270\216Cronjob \347\232\204\344\275\277\347\224\250.md" rename to "docs/26.Job\344\270\216Cronjob \347\232\204\344\275\277\347\224\250.md" diff --git a/docs/27. Service.md b/docs/27.Service.md similarity index 100% rename from docs/27. Service.md rename to docs/27.Service.md diff --git a/docs/28. ConfigMap.md b/docs/28.ConfigMap.md similarity index 100% rename from docs/28. ConfigMap.md rename to docs/28.ConfigMap.md diff --git a/docs/29. Secret.md b/docs/29.Secret.md similarity index 100% rename from docs/29. Secret.md rename to docs/29.Secret.md diff --git a/docs/30. RBAC.md b/docs/30.RBAC.md similarity index 100% rename from docs/30. RBAC.md rename to docs/30.RBAC.md diff --git "a/docs/31. \351\203\250\347\275\262 Wordpress \347\244\272\344\276\213.md" "b/docs/31.\351\203\250\347\275\262 Wordpress \347\244\272\344\276\213.md" similarity index 100% rename from "docs/31. \351\203\250\347\275\262 Wordpress \347\244\272\344\276\213.md" rename to "docs/31.\351\203\250\347\275\262 Wordpress \347\244\272\344\276\213.md" diff --git "a/docs/32. DaemonSet \344\270\216 StatefulSet.md" "b/docs/32.DaemonSet \344\270\216 StatefulSet.md" similarity index 100% rename from "docs/32. DaemonSet \344\270\216 StatefulSet.md" rename to "docs/32.DaemonSet \344\270\216 StatefulSet.md" diff --git a/docs/33. PV.md b/docs/33.PV.md similarity index 100% rename from docs/33. PV.md rename to docs/33.PV.md diff --git a/docs/34. PVC.md b/docs/34.PVC.md similarity index 100% rename from docs/34. PVC.md rename to docs/34.PVC.md diff --git a/docs/35. StorageClass.md b/docs/35.StorageClass.md similarity index 100% rename from docs/35. StorageClass.md rename to docs/35.StorageClass.md diff --git a/docs/36. Jenkins Slave.md b/docs/36.Jenkins Slave.md similarity index 100% rename from docs/36. Jenkins Slave.md rename to docs/36.Jenkins Slave.md diff --git a/docs/37. Jenkins Pipeline.md b/docs/37.Jenkins Pipeline.md similarity index 100% rename from docs/37. Jenkins Pipeline.md rename to docs/37.Jenkins Pipeline.md diff --git a/docs/38. Jenkins BlueOcean.md b/docs/38.Jenkins BlueOcean.md similarity index 100% rename from docs/38. Jenkins BlueOcean.md rename to docs/38.Jenkins BlueOcean.md diff --git "a/docs/39. \346\234\215\345\212\241\345\217\221\347\216\260.md" b/docs/39.kubedns.md similarity index 99% rename from "docs/39. \346\234\215\345\212\241\345\217\221\347\216\260.md" rename to docs/39.kubedns.md index de85d5c992a1df3d2666d59e0858a55bf0ac6863..754dd8895ec8c230685809c3b53a6642100633f9 100644 --- "a/docs/39. \346\234\215\345\212\241\345\217\221\347\216\260.md" +++ b/docs/39.kubedns.md @@ -169,7 +169,7 @@ data: | widget.com | 上游 DNS (8.8.8.8, 8.8.4.4,其中之一) | -另外我们还可以为每个 Pod 设置 DNS 策略。 当前 Kubernetes 支持两种 Pod 特定的 DNS 策略:“Default” 和 “ClusterFirst”。 可以通过 dnsPolicy 标志来指定这些策略。 +另外我们还可以为每个 Pod 设置 DNS 策略。 当前 Kubernetes 支持两种 Pod 特定的 DNS 策略:“Default” 和 “ClusterFirst”。 可以通过 dnsPolicy 标志来指定这些策略。 > 注意:**Default** 不是默认的 DNS 策略。如果没有显式地指定**dnsPolicy**,将会使用 **ClusterFirst** diff --git a/docs/40. ingress.md b/docs/40.ingress.md similarity index 99% rename from docs/40. ingress.md rename to docs/40.ingress.md index 558d24b5d3fd35fd25f1218bb4bb019666e6bef3..9d1e9080b279999f09210202baa8ba0b1ee74f01 100644 --- a/docs/40. ingress.md +++ b/docs/40.ingress.md @@ -198,6 +198,7 @@ ingress.extensions "traefik-web-ui" created ![traefik health](./images/ingress-config3.png) * 第三步,上面我们可以通过自定义域名加上端口可以访问我们的服务了,但是我们平时服务别人的服务是不是都是直接用的域名啊,http 或者 https 的,几乎很少有在域名后面加上端口访问的吧?为什么?太麻烦啊,端口也记不住,要解决这个问题,怎么办,我们只需要把我们上面的 traefik 的核心应用的端口隐射到 master 节点上的 80 端口,是不是就可以了,因为 http 默认就是访问 80 端口,但是我们在 Service 里面是添加的一个 NodePort 类型的服务,没办法隐射 80 端口,怎么办?这里就可以直接在 Pod 中指定一个 hostPort 即可,更改上面的 traefik.yaml 文件中的容器端口: + ```yaml containers: - image: traefik @@ -209,10 +210,12 @@ ports: - name: admin containerPort: 8080 ``` + 添加以后`hostPort: 80`,然后更新应用: ```shell $ kubectl apply -f traefik.yaml ``` + 更新完成后,这个时候我们在浏览器中直接使用域名方法测试下: ![traefik dashboard](./images/ingress-config4.png) diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000000000000000000000000000000000..dbb95fef39f1b04ee136e93b70985868d4d49d5c --- /dev/null +++ b/docs/index.md @@ -0,0 +1,42 @@ +# 从Docker到Kubernetes进阶 + +## 介绍 + +[Kubernetes](http://kubernetes.io/)是Google基于Borg开源的容器编排调度引擎,作为[CNCF](http://cncf.io/)(Cloud Native Computing Foundation)最重要的组件之一,它的目标不仅仅是一个编排系统,而是提供一个规范,可以让你来描述集群的架构,定义服务的最终状态,`Kubernetes` 可以帮你将系统自动地达到和维持在这个状态。`Kubernetes` 作为云原生应用的基石,相当于一个云操作系统,其重要性不言而喻。 + +![从Docker到Kubernetes进阶](http://sdn.haimaxy.com/covers/2018/4/21/c4082e0f09c746aa848279a2567cffed.png) + +之前一直有同学跟我说我 `Docker` 掌握得还可以,但是不知道怎么使用 `Kubernetes`,网上的其他关于 `Kubernetes` 的课程费用又太高,本书就是为你们准备的,当然如果你不了解 `Docker`,不了解 `Kubernetes`,都没有关系,我们会从 `Docker` 入门一步步深入,到 `Kubernetes` 的进阶使用的。所以大家完全没必要担心。 + +学完本课程以后,你将会对 `Docker` 和 `Kubernetes` 有一个更加深入的认识,我们会讲到: + +* `Docker` 的一些常用方法,当然我们的重点会在 Kubernetes 上面 +* 会用 `kubeadm` 来搭建一套 `Kubernetes` 的集群 +* 理解 `Kubernetes` 集群的运行原理 +* 常用的一些控制器使用方法 +* 还有 `Kubernetes` 的一些调度策略 +* `Kubernetes`的运维 +* 包管理工具 `Helm` 的使用 +* 最后我们会实现基于 Kubernetes 的 CI/CD + + +GitHub地址:[https://github.com/cnych/kubernetes-learning/tree/master/docs](https://github.com/cnych/kubernetes-learning/) + +视频课程在线地址:[https://www.haimaxy.com/course/6n8xd6/](https://www.haimaxy.com/course/6n8xd6/) + + +## 社区&读者交流 + +* 博客:[阳明的博客](https://blog.qikqiak.com/) +* 微信群:`k8s`技术圈,扫描我的微信二维码,[阳明](https://blog.qikqiak.com/page/about/),或直接搜索微信号**iEverything**后拉您入群,请增加备注(k8s或kubernetes) +* 知乎专栏:[k8s技术圈](https://zhuanlan.zhihu.com/kube100) +* 开发者头条:[k8s技术圈](https://toutiao.io/subjects/268333) +* 微信公众号:扫描下面的二维码关注微信公众号`k8s技术圈` + +![k8s公众帐号](./images/k8s-qrcode.png) + +* 优点知识:[优点知识](https://www.haimaxy.com/)是一个综合的技术学习平台,本书配套的视频教程将会发布在该平台上面,感兴趣的朋友可以扫描下发的二维码关注自己感兴趣的课程。 + +![优点知识服务号](./images/ydzs-qrcode.png) +![优点知识小程序](./images/ydzs-xcx.png) +