From 72ab62188552abf27e9725f48f47cd0f4a59230d Mon Sep 17 00:00:00 2001 From: "huanqing.shao" Date: Thu, 10 Oct 2019 10:02:26 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=8A=E6=96=AD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vuepress/config.js | 11 +- README.md | 2 + learning/k8s-advanced/index.md | 1 + learning/k8s-advanced/logs/cluster.md | 2 +- learning/k8s-advanced/logs/elk.md | 12 ++ learning/k8s-advanced/logs/node.md | 2 +- learning/k8s-advanced/ts/application.md | 204 ++++++++++++++++++++++++ overview/share-coder.md | 3 - 8 files changed, 230 insertions(+), 7 deletions(-) create mode 100644 learning/k8s-advanced/logs/elk.md create mode 100644 learning/k8s-advanced/ts/application.md diff --git a/.vuepress/config.js b/.vuepress/config.js index 13a3e26..79c5f85 100644 --- a/.vuepress/config.js +++ b/.vuepress/config.js @@ -414,7 +414,14 @@ module.exports = { path: '/learning/k8s-advanced/index', children: [ { - title: 'Kubernetes 日志', + title: '问题诊断', + collapsable: true, + children: [ + 'k8s-advanced/ts/application', + ] + }, + { + title: '日志', collapsable: true, children: [ 'k8s-advanced/logs/', @@ -422,7 +429,7 @@ module.exports = { 'k8s-advanced/logs/node', 'k8s-advanced/logs/cluster', ] - } + }, ] }, { diff --git a/README.md b/README.md index 13ae36e..e2dd552 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,8 @@ Kubernetes教程的主要依据是:Kubernetes 官网文档,以及使用 Kubo ### Kubernetes高级 + * 问题诊断 + * 日志 * Kubernetes 日志可视化 * Kubernetes 监控 * Kubernetes 联邦 diff --git a/learning/k8s-advanced/index.md b/learning/k8s-advanced/index.md index 0a52be0..b52c953 100644 --- a/learning/k8s-advanced/index.md +++ b/learning/k8s-advanced/index.md @@ -8,6 +8,7 @@ description: Kubernetes教程_高级篇_主要涉及日志采集_安全_监控_ Kubernetes教程的深入篇部分,主要涉及的内容有如下几个方面: +* [问题诊断](./ts/application.html) * [Kubernetes 日志](./logs/) * Kubernetes 安全 * Kubernetes 监控 diff --git a/learning/k8s-advanced/logs/cluster.md b/learning/k8s-advanced/logs/cluster.md index 73b138d..a8e05b8 100644 --- a/learning/k8s-advanced/logs/cluster.md +++ b/learning/k8s-advanced/logs/cluster.md @@ -1,7 +1,7 @@ --- vssueId: 125 layout: LearningLayout -description: Kubernetes教程_本文介绍了如何使用kubectl_Kuboard查看和浏览Kubernetes上的节点_容器组_部署等信息_并依据这些信息作出问题诊断 +description: Kubernetes教程_Kubernetes 中并不默认提供集群级别的日志,不过,有许多种途径可以和集群级别的日志整合。例如:在每个节点上配置日志代理_在应用程序的Pod中包含一个专门用于收集日志的sidecar容器_从应用程序中直接推送日志到日志存储端 meta: - name: keywords content: Kubernetes教程,K8S教程,日志,Logging diff --git a/learning/k8s-advanced/logs/elk.md b/learning/k8s-advanced/logs/elk.md new file mode 100644 index 0000000..b8ad27e --- /dev/null +++ b/learning/k8s-advanced/logs/elk.md @@ -0,0 +1,12 @@ +--- +vssueId: 125 +layout: LearningLayout +description: Kubernetes教程_本章节中 +meta: + - name: keywords + content: Kubernetes教程,K8S教程,日志,Logging +--- + +# 使用ELK作为集群级别的日志 + +待更新 ... diff --git a/learning/k8s-advanced/logs/node.md b/learning/k8s-advanced/logs/node.md index 44920d7..dd8ff19 100644 --- a/learning/k8s-advanced/logs/node.md +++ b/learning/k8s-advanced/logs/node.md @@ -1,7 +1,7 @@ --- vssueId: 125 layout: LearningLayout -description: Kubernetes教程_本文介绍了如何使用kubectl_Kuboard查看和浏览Kubernetes上的节点_容器组_部署等信息_并依据这些信息作出问题诊断 +description: Kubernetes教程_容器化应用程序写入到stdout和stderr中的任何信息,都将被容器引擎重定向到某个地方。例如Docker容器引擎将 `stdout` 和stderr这两个输出流重定向到logging-driver meta: - name: keywords content: Kubernetes教程,K8S教程,日志,Logging diff --git a/learning/k8s-advanced/ts/application.md b/learning/k8s-advanced/ts/application.md new file mode 100644 index 0000000..59ba566 --- /dev/null +++ b/learning/k8s-advanced/ts/application.md @@ -0,0 +1,204 @@ +--- +vssueId: 127 +layout: LearningLayout +description: Kubernetes教程_本章节中,您将了解到如何在 Kubernetes 中使用最基本的日志,此时,日志信息将输出到标准输出流(standard output stream)。 +meta: + - name: keywords + content: Kubernetes教程,K8S教程,诊断应用程序,问题诊断 +--- + +# 诊断应用程序 + +> 参考文档: [Troubleshoot Applications](https://kubernetes.io/docs/tasks/debug-application-cluster/debug-application/) + +本文档可帮助您诊断部署到Kubernetes中的应用程序所出现的问题。 + +诊断问题的第一步是对问题做个分类,该问题是Pod的问题、Deployment(StatefulSet/DaemonSet)控制器的问题,还是Service的问题? + +## Debugging Pods + +任何时候,当你怀疑Pod碰到问题时,先看一下Pod的完整描述。执行如下语句可以查看到Pod最新的状态以及最近关联的事件: + +``` sh +kubectl describe pods ${POD_NAME} +``` + +输出结果如下所示: +``` {19,22,26,41} +Name: nginx-deployment-5754944d6c-d8hs8 +Namespace: default +Priority: 0 +Node: demo-worker002/172.17.216.82 +Start Time: Wed, 02 Oct 2019 22:36:19 +0800 +Labels: app=nginx + pod-template-hash=5754944d6c +Annotations: cni.projectcalico.org/podIP: 192.168.15.129/32 +Status: Running +IP: 192.168.15.129 +Controlled By: ReplicaSet/nginx-deployment-5754944d6c +Containers: + nginx: + Container ID: docker://70b70667e082d6b4cbc7ab7a5fba33c2fa93509e08794658fde9ad9ac04a0327 + Image: nginx:1.7.9 + Image ID: docker-pullable://nginx@sha256:e3456c851a152494c3e4ff5fcc26f240206abac0c9d794affb40e0714846c451 + Port: 80/TCP + Host Port: 0/TCP + State: Running + Started: Wed, 02 Oct 2019 22:36:22 +0800 + Ready: True + Restart Count: 0 + Environment: + Mounts: + /var/run/secrets/kubernetes.io/serviceaccount from default-token-s6znq (ro) +Conditions: + Type Status + Initialized True + Ready True + ContainersReady True + PodScheduled True +Volumes: + default-token-s6znq: + Type: Secret (a volume populated by a Secret) + SecretName: default-token-s6znq + Optional: false +QoS Class: BestEffort +Node-Selectors: +Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s + node.kubernetes.io/unreachable:NoExecute for 300s +Events: +``` + +查看Pod中容器的状态:是否所有的容器都处于 `Running` 状态?是否近期有重启过?根据Pod/容器的状态: + +### Pod一直是Pending + +如果 Pod 一直停留在 `Pending`,意味着该 Pod 不能被调度到某一个节点上。通常,这是因为集群中缺乏足够的资源或者 ***“合适”*** 的资源。在上述 `kubectl describe...` 命令的输出中的 `Events` 字段,会有对应的事件描述为什么 Pod 不能调度到节点上。可能的原因有: +* **缺乏足够的资源**:可能集群中的CPU或内存都已经耗尽,此时,您可以尝试: + * 删除某些 Pod + * 调整Pod的资源请求 + * 向集群中添加新的节点 + ::: tip + 也许您会觉得节点的CPU或内存使用实际很低,资源耗尽这个现象不应该出现,如果带有此疑问,请参考 [带有资源请求的容器组是如何调度的](/learning/k8s-intermediate/config/computing-resource.html#带有资源请求的容器组是如何调度的) + ::: +* **该Pod使用`hostPort`**: 当Pod使用 `hostPort` 时,该Pod可以调度的地方就比较有限了。大多数情况下,是不需要使用 `hostPort` 的,可以尝试使用 Service 访问您的 Pod。如果您确实需要使用 `hostPort` 时,Deployment/ReplicationController 中 replicas 副本数不能超过集群中的节点数,因为每台机器的 80 端口只有一个,任何其他端口也只有一个。如果该端口被其他程序占用了,也将导致Pod调度不成功 +* **污点和容忍**: 当您在Pod的事件中看到 `Taints` 或 `Tolerations` 这两个单词时,请您先参考文档 [污点和容忍](/learning/k8s-intermediate/config/taints-toleration/),确保您理解了这两个概念 + +### Pod一直是Wating + +如果 Pod 停留在 `Waiting` 状态,此时该 Pod 已经被调度到某个节点上了,但是却不能运行。在上述 `kubectl describe ...` 命令的输出中,仍然注意 `Events` 字段的内容。最常见的 Pod 停留在 `Waiting` 状态的原因是抓取容器镜像失败。请检查: +* 容器镜像的名字是对的 +* 容器镜像已经推送到了镜像仓库中 +* 在对应的节点上手工执行 `docker pull ` 命令,看是否能够抓取成功 +* 如果使用私有镜像仓库,请参考 [使用私有仓库中的docker镜像](/learning/k8s-intermediate/private-registry.html) + +### Pod已经Crash或者Unhealthy + +此时通常是容器中应用程序的问题,您可以查看一下容器的日志,以诊断容器中应用程序出现了何种故障: + +``` sh +kubectl logs ${POD_NAME} ${CONTAINER_NAME} +``` + +如果容器之前 crash,通过上述命令查不到日志,可以尝试使用下面的命令查看上一次 crash 时的日志: + +``` sh +kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME} +``` + +或者,也可以执行容器中的命令: +``` sh +kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN} +``` + +::: tip +上述命令中的 `${CONTAINER_NAME}` 或者 `-c ${CONTAINER_NAME}` 都是可选项,当你的 Pod 中只有一个容器时,可以不填写此参数 +::: + +例如,要查看 Pod `Cassandra` 的日志,可以执行命令: +``` sh +kubectl exec cassandra -- cat /var/log/cassandra/system.log +``` + +### Pod处于Running状态,但是不工作 + +Pod已经处于Running状态了,但是不像您期望的那样工作,此时,很有可能是您的部署描述yaml文件(例如 Pod、Deployment、StatefulSet等)出现了问题,而创建是,kubectl 忽略了该错误。例如环境变量中某一个 Key 写错了,`command` 拼写成了 `commnd` 等。如果 `command` 拼写成了 `commnd`,您仍然能够使用该 yaml 文件创建工作负载,但是容器在运行时,却不会使用您原本期望的命令,而是执行了镜像中的 `EntryPoint`。 + +* 首先,在使用 `kubectl apply -f` 命令之前,可以尝试为其添加 `--validate` 选项,例如, `kubectl apply --validate -f mypod.yaml`。如果您将 `command` 拼写成 `commnd`,将看到如下错误信息: + + ``` sh + I0805 10:43:25.129850 46757 schema.go:126] unknown field: commnd + I0805 10:43:25.129973 46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842 + pods/mypod + ``` + + ::: tip + 使用 Kuboard 创建工作负载时,可以避免 yaml 格式的错误 + ::: + +* 其次,请检查您已经创建的 Pod 和您预期的是一致的。执行命令 `kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml`。将输出结果与您创建 Pod 时所使用的文件做一个对比。通常通过此命令从服务器端获取到的信息比创建 Pod 时所使用的文件要多几行,这是正常的。然而,如果您创建的Pod时所示用的文件中,存在从服务器上获取的信息中没有的代码行,这可能就是问题所在了。 + +### Debugging Deployment + +Deployment(或者 DaemonSet/StatefulSet/Job等),都会比较直接,他们要么可以创建 Pod,要么不可以,此时,请按照上面的方法检查 Pod 的问题。 + +您也可以通过 `kubectl describe deployment ${DEPLOYMENT_NAME}` (或者statefulset / job 等)命令查看与 Deployment 相关的事件,来发现到底出了什么问题。 + +如果使用 StatefulSet,您有可能会碰到 `卡死` 的问题,请参考文档 [Forced Rollback](/learning/k8s-intermediate/workload/wl-statefulset/update.html#rolling-updates) + +### Debugging Service + +Service 可以为一组 Pod 提供负载均衡的功能。与Service相关,存在着几类常见问题。请参考本章节了解如何定位 Service 的问题: + +首先,检查Service的Endpoints。参考此文档,[Service详细描述](/learning/k8s-intermediate/service/service-details.html) 可以了解 Service 和 Endpoints。 + +执行如下命令: +``` sh +kubectl get endpoints ${SERVICE_NAME} +``` + +输出结果如下所示: +``` sh +NAME ENDPOINTS AGE +web-kuboard-press 192.168.144.158:80,192.168.199.135:80 70d +``` + +请确保 enpoints 的个数与您期望与该 Service 匹配的 Pod 的个数是相同的。例如,如果您使用 Deployment 部署了 web-kuboard-press,副本数为 2,此时,在输出结果的 ENDPOINTS 字段,应该有两个不同的 IP 地址。 + +### Service中没有Endpoints + +如果您的Service中没有Enpoints,请尝试使用 Service 的 label selector 查询一下是否存在 Pod。假设您的 Service 如下: + +``` yaml +... +metadata: + name: myservice + namespace: ns1 +spec: + - selector: + name: nginx + type: frontend +... +``` + +执行如下命令可以查看 Service 所匹配的 Pod: +``` sh +kubectl get pods --selector=name=nginx,type=frontend -n ns1 +``` + +请核对查出来的 Pod 列表是否是您期望使用的 Pod。 + +如果 Pod 列表是您期望的结果,但是 ENDPOINTS 还是空的,此时很可能是您没有为 Service 指定正确的端口。如果 Service 中指定的 `containerPort` 实际上并不存在于 Pod 中,该 Pod 不会被添加到 ENDPOINTS 列表里。请确保 Service 指定的 `containerPort` 在 Pod 中是可以访问的。 + +### 网络转发问题 + +如果您的客户端可以连接上 Service,但是连接很快就被断开了,并且 endpoints 中有合适的内容,此时,有可能是 proxy 不能转发到您的 Pod 上。 + +请检查: +* Pod是否正常工作?`kubectl get pods` 查看 Pod 的 restart count,并按照本文前面的步骤诊断一下 Pod 是否有问题 +* 是否可以直接连接到 Pod ?`kubectl get pods -o wide` 可以获得 Pod 的IP地址,从任意一个节点上执行 `ping ` 命令,确认网络连接是否正常 +* 应用程序是否正常地监听了端口?Kubernetes 不对网络端口做映射,如果您的应用程序监听 8080 端口,则您在 Service 中应该指定 `containerPort` 为 8080。在任意节点上执行命令 `curl :` 可查看 Pod 中容器的端口是否正常。参考 [Kubernetes的网络模型](/learning/k8s-intermediate/service/connecting.html#kubernetes-的网络模型) + + +## 如果还碰到问题 + +请加本文末尾的QQ群答疑。也可以了解 [更多支持方式](/support/) diff --git a/overview/share-coder.md b/overview/share-coder.md index e79d9ea..f187fc1 100644 --- a/overview/share-coder.md +++ b/overview/share-coder.md @@ -22,9 +22,6 @@ Kubernetes 容器编排已越来越被大家关注,然而学习 Kubernetes 的 * Kuboard 官网提供 Spring Cloud 等微服务参考架构在 K8S 上的详细部署文档和步骤,是 Spring Cloud 用户将自己的应用迁移到 K8S 部署环境的非常好的参考资料。 - -Kuboard 官网地址:[https://kuboard.cn](https://kuboard.cn/#from_coder_toutiao) - Kuboard 发布不到两个月时间,github star 已经迅速增长到 461,获得了许多用户的喜爱。