diff --git a/.vuepress/components/HomePage.vue b/.vuepress/components/HomePage.vue index 79f5914..dcb19d4 100644 --- a/.vuepress/components/HomePage.vue +++ b/.vuepress/components/HomePage.vue @@ -213,7 +213,7 @@ export default { height 240px padding: 1rem .intro - margin-top 1rem + margin-top 2rem .intro_text margin-right 1rem height calc(339px - 2rem) diff --git a/.vuepress/config.js b/.vuepress/config.js index 56dfa67..96dee03 100644 --- a/.vuepress/config.js +++ b/.vuepress/config.js @@ -21,7 +21,7 @@ module.exports = { markdown: { toc: { includeLevel: [2, 3] }, lineNumbers: true, - externalLinks: { target: '_blank', rel: 'noopener noreferrer', onclick: 'openOutboundLink(this)' } + externalLinks: { target: '_blank', rel: 'nofollow', onclick: 'openOutboundLink(this)' } }, dest: 'docs', plugins: { @@ -62,6 +62,7 @@ module.exports = { // zIndex: 10000, // }, // }, + 'vuepress-plugin-smooth-scroll': {}, 'code-switcher': {}, 'reading-progress': {}, 'vuepress-plugin-element-tabs': {}, @@ -193,14 +194,15 @@ module.exports = { ], '/learning/': [ - '', { title: 'Kubernetes 介绍', collapsable: true, sidebarDepth: 3, children: [ + '', 'k8s-bg/what-is-k8s', 'k8s-bg/component', + ] }, { @@ -221,7 +223,31 @@ module.exports = { title: 'Kubernetes 进阶', collapsable: true, children: [ - 'k8s-intermediate/private-registry', + { + title: '架构', + collapsable: true, + children: [ + { + title: '节点', + collapsable: true, + path: '/learning/k8s-bg/architecture/nodes', + children: [ + 'k8s-bg/architecture/nodes', + 'k8s-bg/architecture/nodes-mgmt', + ] + }, + { + title: '集群内的通信', + collapsable: true, + path: '/learning/k8s-bg/architecture/com', + children: [ + 'k8s-bg/architecture/com', + 'k8s-bg/architecture/com-n-m', + 'k8s-bg/architecture/com-m-n', + ] + }, + ] + }, { title: '工作负载', collapsable: true, @@ -296,6 +322,7 @@ module.exports = { title: '配置', collapsable: true, children: [ + 'k8s-intermediate/private-registry', 'k8s-intermediate/config/config-map', 'k8s-intermediate/config/computing-resource', 'k8s-intermediate/config/assign-pod-node', @@ -339,6 +366,7 @@ module.exports = { 'k8s-intermediate/config/sec-ctx/con-sel', 'k8s-intermediate/config/sec-ctx/volumes', 'k8s-intermediate/config/sec-ctx/pod-kuboard', + 'k8s-intermediate/config/sec-ctx/con-kuboard', ] }, ] diff --git a/learning/k8s-bg/architecture/com-m-n.md b/learning/k8s-bg/architecture/com-m-n.md new file mode 100644 index 0000000..2ea2057 --- /dev/null +++ b/learning/k8s-bg/architecture/com-m-n.md @@ -0,0 +1,42 @@ +--- +vssueId: 120 +layout: LearningLayout +description: Kubernete教程_Kubernetes组件_从 master(apiserver)到Cluster存在着两条主要的通信路径,第一种:apiserver 访问集群中每个节点上的 kubelet 进程;第二种:使用 apiserver 的 proxy 功能,从 apiserver 访问集群中的任意节点、Pod、Service + +meta: + - name: keywords + content: Kubernetes 教程,Kubernetes Master-Node通信 +--- + +# Master to Cluster + +从 master(apiserver)到Cluster存在着两条主要的通信路径: +* apiserver 访问集群中每个节点上的 kubelet 进程 +* 使用 apiserver 的 proxy 功能,从 apiserver 访问集群中的任意节点、Pod、Service + +## apiserver to kubelet + +apiserver 在如下情况下访问 kubelet: +* 抓取 Pod 的日志 +* 通过 `kubectl exec -it` 指令(或 kuboard 的终端界面)获得容器的命令行终端 +* 提供 `kubectl port-forward` 功能 + +这些连接的访问端点是 kubelet 的 HTTPS 端口。默认情况下,apiserver 不校验 kubelet 的 HTTPS 证书,这种情况下,连接可能会收到 man-in-the-middle 攻击,因此该连接如果在不受信网络或者公网上运行时,是 **不安全** 的。 + +如果要校验 kubelet 的 HTTPS 证书,可以通过 `--kubelet-certificate-authority` 参数为 apiserver 提供校验 kubelet 证书的根证书。 + +如果不能完成这个配置,又需要通过不受信网络或公网将节点加入集群,则需要使用 [SSH隧道](#SSH隧道) 连接 apiserver 和 kubelet。 + +同时,[Kubelet authentication/authorization](https://kubernetes.io/docs/admin/kubelet-authentication-authorization/) 需要激活,以保护 kubelet API + +## apiserver to nodes, pods, services + +从 apiserver 到 节点/Pod/Service 的连接使用的是 HTTP 连接,没有进行身份认证,也没有进行加密传输。您也可以通过增加 `https` 作为 节点/Pod/Service 请求 URL 的前缀,但是 HTTPS 证书并不会被校验,也无需客户端身份认证,因此该连接是无法保证一致性的。目前,此类连接如果运行在非受信网络或公网上时,是 **不安全** 的 + +## SSH隧道 + +Kubernetes 支持 SSH隧道(tunnel)来保护 Master --> Cluster 访问路径。此时,apiserver 将向集群中的每一个节点建立一个 SSH隧道(连接到端口22的ssh服务)并通过隧道传递所有发向 kubelet、node、pod、service 的请求。 + +::: warning deprecated +SSH隧道当前已被不推荐使用(deprecated),Kubernetes 正在设计新的替代通信方式。 +::: diff --git a/learning/k8s-bg/architecture/com-n-m.md b/learning/k8s-bg/architecture/com-n-m.md new file mode 100644 index 0000000..f901067 --- /dev/null +++ b/learning/k8s-bg/architecture/com-n-m.md @@ -0,0 +1,18 @@ +--- +vssueId: 120 +layout: LearningLayout +description: Kubernete教程_Kubernetes组件_所有从集群(worker 节点)访问 Master 节点的通信,都是针对 apiserver 的(没有任何其他 master 组件发布远程调用接口)。通常安装 Kubernetes 时,apiserver 监听 HTTPS 端口(443),并且配置了一种或多种客户端认证方式 authentication +meta: + - name: keywords + content: Kubernetes 教程,Kubernetes Master-Node通信 +--- + +# Cluster to Master + +所有从集群访问 Master 节点的通信,都是针对 apiserver 的(没有任何其他 master 组件发布远程调用接口)。通常安装 Kubernetes 时,apiserver 监听 HTTPS 端口(443),并且配置了一种或多种 [客户端认证方式 authentication](https://kubernetes.io/docs/reference/access-authn-authz/authentication/)。至少需要配置一种形式的 [授权方式 authorization](https://kubernetes.io/docs/reference/access-authn-authz/authorization/),尤其是 [匿名访问 anonymous requests](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#anonymous-requests) 或 [Service Account Tokens](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens) 被启用的情况下。 + +节点上必须配置集群(apiserver)的公钥根证书(public root certificate),此时,在提供有效的客户端身份认证的情况下,节点可以安全地访问 APIServer。例如,在 Google Kubernetes Engine 的一个默认 Kubernetes 安装里,通过客户端证书为 kubelet 提供客户端身份认证。请参考 [kubelet TLS bootstrapping](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/),了解如何自动为 kubelet 提供客户端证书。 + +对于需要调用 APIServer 接口的 Pod,应该为其关联 Service Account,此时,Kubernetes将在创建Pod时自动为其注入公钥根证书(public root certificate)以及一个有效的 bearer token(放在HTTP请求头Authorization字段)。所有名称空间中,都默认配置了名为 `kubernetes` Kubernetes Service,该 Service对应一个虚拟 IP(默认为 10.96.0.1),发送到该地址的请求将由 kube-proxy 转发到 apiserver 的 HTTPS 端口上。请参考 [Service连接应用程序](/learning/k8s-intermediate/service/connecting.html) 了解 Kubernetes Service 是如何工作的。 + +得益于这些措施,默认情况下,从集群(节点以及节点上运行的 Pod)访问 master 的连接是安全的,因此,可以通过不受信的网络或公网连接 Kubernetes 集群 diff --git a/learning/k8s-bg/architecture/com.md b/learning/k8s-bg/architecture/com.md new file mode 100644 index 0000000..6a7db9a --- /dev/null +++ b/learning/k8s-bg/architecture/com.md @@ -0,0 +1,18 @@ +--- +vssueId: 120 +layout: LearningLayout +description: Kubernete教程_Kubernetes组件_本文描述了Kubernetes集群和Master节点(实际上是 apiserver)之间的通信路径。用户在自定义集群的安装之前,或者调整集群的网络配置之前必须理解这部分内容 +meta: + - name: keywords + content: Kubernetes 教程,Kubernetes Master-Node通信 +--- + +# Master-Node之间的通信 + +本文描述了Kubernetes集群和Master节点(实际上是 apiserver)之间的通信路径。用户在自定义集群的安装之前,或者调整集群的网络配置之前必须理解这部分内容。例如: +* 从 [安装Kubernetes单Master节点](/install/install-k8s.html) 的安装结果调整到 [安装Kubernetes高可用](/install/install-kubernetes.html) 的安装结果 +* 将公网 IP 地址上的机器作为节点加入到 Kubernetes 集群 + +Master-Node 之间的通信可以分为如下两类: +* [Cluster to Master](./com-n-m.html) +* [Master to Cluster](./com-m-n.html) diff --git a/learning/k8s-bg/architecture/nodes-mgmt.md b/learning/k8s-bg/architecture/nodes-mgmt.md new file mode 100644 index 0000000..06a5f80 --- /dev/null +++ b/learning/k8s-bg/architecture/nodes-mgmt.md @@ -0,0 +1,107 @@ +--- +vssueId: 119 +layout: LearningLayout +description: Kubernete教程_Kubernetes组件 +meta: + - name: keywords + content: Kubernetes 教程,Kubernetes 节点, Kubernetes node +--- + +# 节点管理 + +与 Pod 和 Service 不一样,节点并不是由 Kubernetes 创建的,节点由云供应商(例如,Google Compute Engine、阿里云等)创建,或者节点已经存在于您的物理机/虚拟机的资源池。向 Kubernetes 中创建节点时,仅仅是创建了一个描述该节点的 API 对象。节点 API 对象创建成功后,Kubernetes将检查该节点是否有效。例如,假设您创建如下节点信息: + +``` yaml +kind: Node +apiVersion: v1 +metadata: + name: "10.240.79.157" + labels: + name: "my-first-k8s-node" +``` + +Kubernetes 在 APIServer 上创建一个节点 API 对象(节点的描述),并且基于 `metadata.name` 字段对节点进行健康检查。如果节点有效([节点组件](/learning/k8s-bg/component.html#node-组件)正在运行),则可以向该节点调度 Pod;否则,该节点 API 对象将被忽略,知道节点变为有效状态。 + +::: tip +Kubernetes 将保留无效的节点 API 对象,并不断地检查该节点是否有效。除非您使用 `kubectl delete node my-first-k8s-node` 命令删除该节点。 +::: + +## 节点控制器(Node Controller) + +节点控制器是一个负责管理节点的 Kubernetes master 组件。在节点的生命周期中,节点控制器起到了许多作用。 + +* **首先**,节点控制器在注册节点时为节点分配 [CIDR](/glossary/cidr.html) 地址块 +* **第二**,节点控制器通过云供应商([cloud-controller-manager](learning/k8s-bg/component.html#cloud-controller-manager))接口检查节点列表中每一个节点对象对应的虚拟机是否可用。在云环境中,只要节点状态异常,节点控制器检查其虚拟机在云供应商的状态,如果虚拟机不可用,自动将节点对象从 APIServer 中删除。 +* **第三**,节点控制器监控节点的健康状况。当节点变得不可触达时(例如,由于节点已停机,节点控制器不再收到来自节点的心跳信号),节点控制器将节点API对象的 `NodeStatus` Condition 取值从 `NodeReady` 更新为 `Unknown`;然后在等待 `pod-eviction-timeout` 时间后,将节点上的所有 Pod 从节点驱逐。 + > * 默认40秒未收到心跳,修改 `NodeStatus` Condition 为 `Unknown`; + > * 默认 `pod-eviction-timeout` 为 5分钟 + > * 节点控制器每隔 `--node-monitor-period` 秒检查一次节点的状态 + +在 Kubernetes v1.13 以前,NodeStatus 记录了从节点发出的心跳信号。从 Kubernetes v1.13 开始,node lease 特性进入 alpha 阶段([KEP-0009](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/0009-node-heartbeat.md))。当 node lease 特性被启用时,每个节点都有一个 `kube-node-lease` 名称空间下对应的 `Lease` 对象,节点控制器周期性地更新 `Lease` 对象;此时 NodeStatus 和 node lease 都被用来记录节点的心跳信号。NodeStatus 的更新频率远高于 node lease,原因是: +* 每次节点向 master 发出心跳信号,NodeStatus 都将被更新 +* 只有在 NodeStatus 发生改变,或者足够长的时间未接收到 NodeStatus 更新时,节点控制器才更新 node lease(默认为1分钟,比节点失联的超时时间40秒要更长) + +> 由于 node lease 比 NodeStatus 更轻量级,该特性显著提高了节点心跳机制的效率,并使 Kubernetes 性能和可伸缩性得到了提升 + +在 Kubernetes v1.4 中,优化了节点控制器的逻辑以便更好的处理大量节点不能触达 master 的情况(例如,master 出现网络故障)。主要的优化点在于,节点控制器在决定是否执行 Pod 驱逐的动作时,会检查集群中所有节点的状态。 + +大多数情况下,节点控制器限制了驱逐 Pod 的速率为 `--node-eviction-rate` (默认值是0.1)每秒,即节点控制器每 10 秒驱逐 1 个 Pod。 + +当节点所在的高可用区出现故障时,节点控制器驱逐 Pod 的方式将不一样。节点控制器驱逐Pod前,将检查高可用区里故障节点的百分比(`NodeReady` Condition 的值为 `Unknown` 或 `False`): +* 如果故障节点的比例不低于 `--unhealthy-zone-threshold`(默认为 0.55),则降低驱逐 Pod 的速率 + * 如果集群规模较小(少于等于 `--large-cluster-size-threshold` 个节点,默认值为 50),则停止驱逐 Pod + * 如果集群规模大于 `--large-cluster-size-threshold` 个节点,则驱逐 Pod 的速率降低到 `--secondary-node-eviction-rate` (默认值为 0.01)每秒 + +针对每个高可用区使用这个策略的原因是,某一个高可用区可能与 master 隔开了,而其他高可用区仍然保持连接。如果您的集群并未分布在云供应商的多个高可用区上,此时,您只有一个高可用区(即整个集群)。 + +将集群的节点分布到多个高可用区最大的原因是,在某个高可用区出现整体故障时,可以将工作负载迁移到仍然健康的高可用区。因此,如果某个高可用区的所有节点都出现故障时,节点控制器仍然使用正常的驱逐 Pod 的速率(`--node-eviction-rate`)。 + +最极端的情况是,所有的高可用区都完全不可用(例如,集群中一个健康的节点都没有),此时节点控制器 master 节点的网络连接出现故障,并停止所有的驱逐 Pod 的动作,直到某些连接得到恢复。 + +自 Kubernetes v1.6 开始,节点控制器同时也负责为带有 `NoExecute` 污点的节点驱逐其上的 Pod。此外,节点控制器还负责根据节点的状态(例如,节点不可用,节点未就绪等)为节点添加污点。参考 [NoExecute](](/learning/k8s-intermediate/config/taints-toleration/#污点与容忍的匹配)) 获取更多信息。 + +自 Kubernetes v1.8 开始,节点控制器可以根据节点的 Condition 为节点添加污点,此特性处于 alpha 阶段 + +## 节点自注册(Self-Registration) + +如果 kubelet 的启动参数 `--register-node`为 true(默认为 true),kubelet 会尝试将自己注册到 API Server。kubelet自行注册时,将使用如下选项: +* `--kubeconfig`:向 apiserver 进行认证时所用身份信息的路径 +* `--cloud-provider`:向云供应商读取节点自身元数据 +* `--register-node`:自动向 API Server 注册节点 +* `--register-with-taints`:注册节点时,为节点添加污点(逗号分隔,格式为 \=\:\ +* `--node-ip`:节点的 IP 地址 +* `--node-labels`:注册节点时,为节点添加标签 +* `--node-status-update-frequency`:向 master 节点发送心跳信息的时间间隔 + +如果 [Node authorization mode](https://kubernetes.io/docs/reference/access-authn-authz/node/) 和 [NodeRestriction admission plugin](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction) 被启用,kubelet 只拥有创建/修改其自身所对应的节点 API 对象的权限。 + +## 手动管理节点 + +集群管理员可以创建和修改节点API对象。 + +如果管理员想要手工创建节点API对象,可以将 kubelet 的启动参数 `--register-node` 设置为 false。 + +管理员可以修改节点API对象(不管是否设置了 `--register-node` 参数)。可以修改的内容有: +* 增加/减少标签 +* 标记节点为不可调度(unschedulable) + +节点的标签与 Pod 上的节点选择器(node selector)配合,可以控制调度方式,例如,限定 Pod 只能在某一组节点上运行。请参考 [将容器组调度到指定的节点](/learning/k8s-intermediate/config/assign-pod-node.html)。 + +执行如下命令可将节点标记为不可调度(unschedulable),此时将阻止新的 Pod 被调度到该节点上,但是不影响任何已经在该节点上运行的 Pod。这在准备重启节点之前非常有用。 +``` sh +kubectl cordon $NODENAME +``` + +::: tip +DaemonSet Controller 创建的 Pod 将绕过 Kubernetes 调度器,并且忽略节点的 unschedulable 属性。因为我们假设 Daemons 守护进程属于节点,尽管该节点在准备重启前,已经排空了上面所有的应用程序。 +::: + +## 节点容量(Node Capacity) + +节点API对象中描述了节点的容量(Capacity),例如,CPU数量、内存大小等信息。通常,节点在向 APIServer 注册的同时,在节点API对象里汇报了其容量(Capacity)。如果您 [手动管理节点](#手动管理节点),您需要在添加节点时自己设置节点的容量。 + +Kubernetes 调度器在调度 Pod 到节点上时,将确保节点上有足够的资源。具体来说,调度器检查节点上所有容器的资源请求之和不大于节点的容量。此时,只能检查由 kubelet 启动的容器,不包括直接由容器引擎启动的容器,更不包括不在容器里运行的进程。 + +如果您想显式地为 Pod 以外的进程预留资源,请参考 [reserve resources for system daemons](https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#system-reserved) + + diff --git a/learning/k8s-bg/architecture/nodes.md b/learning/k8s-bg/architecture/nodes.md new file mode 100644 index 0000000..b385919 --- /dev/null +++ b/learning/k8s-bg/architecture/nodes.md @@ -0,0 +1,183 @@ +--- +vssueId: 119 +layout: LearningLayout +description: Kubernete教程_Kubernetes节点_Kubernetes中节点(node)指的是一个工作机器,曾经叫做minion。不同的集群中,节点可能是虚拟机也可能是物理机。每个节点都由 master 组件管理,并包含了运行 Pod(容器组)所需的服务。 +meta: + - name: keywords + content: Kubernetes 教程,Kubernetes 节点,Kubernetes node +--- + +# 节点 + +Kubernetes中节点(node)指的是一个工作机器,曾经叫做 `minion`。不同的集群中,节点可能是虚拟机也可能是物理机。每个节点都由 master 组件管理,并包含了运行 Pod(容器组)所需的服务。这些服务包括: +* [容器引擎](/learning/k8s-bg/component.html#容器引擎) +* kubelet +* kube-proxy +查看此文档可了解更多细节 [The Kubernetes Node](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/architecture.md#the-kubernetes-node) + +## 节点状态 + +节点的状态包含如下信息: + +* Addresses +* Conditions +* Capacity and Allocatable +* Info + +执行以下命令可查看所有节点的列表: + +``` sh +kubectl get nodes -o wide +``` + + + +执行以下命令可查看节点状态以及节点的其他详细信息: + +``` sh +kubectl describe node +``` + +输出结果如下所示: +``` {16,24,34,41} +Name: demo-worker-temp-01 +Roles: +Labels: beta.kubernetes.io/arch=amd64 + beta.kubernetes.io/os=linux + kubernetes.io/arch=amd64 + kubernetes.io/hostname=demo-worker-temp-01 + kubernetes.io/os=linux +Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock + node.alpha.kubernetes.io/ttl: 0 + projectcalico.org/IPv4Address: 172.17.216.105/20 + projectcalico.org/IPv4IPIPTunnelAddr: 192.168.199.128 + volumes.kubernetes.io/controller-managed-attach-detach: true +CreationTimestamp: Mon, 30 Sep 2019 06:30:16 +0800 +Taints: +Unschedulable: false +Conditions: + Type Status LastHeartbeatTime LastTransitionTime Reason Message + ---- ------ ----------------- ------------------ ------ ------- + NetworkUnavailable False Wed, 02 Oct 2019 22:37:33 +0800 Wed, 02 Oct 2019 22:37:33 +0800 CalicoIsUp Calico is running on this node + MemoryPressure False Sun, 06 Oct 2019 13:44:41 +0800 Mon, 30 Sep 2019 06:30:16 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available + DiskPressure False Sun, 06 Oct 2019 13:44:41 +0800 Mon, 30 Sep 2019 06:30:16 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure + PIDPressure False Sun, 06 Oct 2019 13:44:41 +0800 Mon, 30 Sep 2019 06:30:16 +0800 KubeletHasSufficientPID kubelet has sufficient PID available + Ready True Sun, 06 Oct 2019 13:44:41 +0800 Wed, 02 Oct 2019 22:37:41 +0800 KubeletReady kubelet is posting ready status +Addresses: + InternalIP: 172.17.216.105 + Hostname: demo-worker-temp-01 +Capacity: + cpu: 2 + ephemeral-storage: 41147472Ki + hugepages-1Gi: 0 + hugepages-2Mi: 0 + memory: 7733524Ki + pods: 110 +Allocatable: + cpu: 2 + ephemeral-storage: 37921510133 + hugepages-1Gi: 0 + hugepages-2Mi: 0 + memory: 7631124Ki + pods: 110 +System Info: + Machine ID: 20190711105006363114529432776998 + System UUID: 841EC123-F92C-4A3A-BEC0-DAADDD625067 + Boot ID: 70c08b02-45ed-456f-8deb-b5c0ebeab414 + Kernel Version: 3.10.0-957.21.3.el7.x86_64 + OS Image: CentOS Linux 7 (Core) + Operating System: linux + Architecture: amd64 + Container Runtime Version: docker://18.9.7 + Kubelet Version: v1.16.0 + Kube-Proxy Version: v1.16.0 +Non-terminated Pods: (21 in total) + Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE + --------- ---- ------------ ---------- --------------- ------------- --- + default nginx-deployment-5754944d6c-8lnlx 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d14h + example gateway-example-6f6f45cd6-mhggv 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d14h + example monitor-grafana-ff99b5b6f-sxppz 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d14h + kube-system calico-node-qjfqd 250m (12%) 0 (0%) 0 (0%) 0 (0%) 6d7h + kube-system eip-nfs-cluster-storage-6c9c7d46f4-lmxql 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d14h + kube-system kube-proxy-4xz9h 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d15h + kube-system monitor-prometheus-node-exporter-t7d24 0 (0%) 0 (0%) 0 (0%) 0 (0%) 2d20h + kuboard-blog cloud-busybox-867645c5dd-7l97b 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d14h + kuboard-blog db-wordpress-79d88d66b7-j7kj8 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d14h + kuboard-press svc-busybox-6cc877b848-2kl28 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3d14h + kuboard-press web-kuboard-press-6d6f8bdbb8-c4q44 0 (0%) 0 (0%) 0 (0%) 0 (0%) 2d3h + nginx-ingress nginx-ingress-hsv26 0 (0%) 0 (0%) 0 (0%) 0 (0%) 6d7h +Allocated resources: + (Total limits may be over 100 percent, i.e., overcommitted.) + Resource Requests Limits + -------- -------- ------ + cpu 250m (12%) 0 (0%) + memory 0 (0%) 0 (0%) + ephemeral-storage 0 (0%) 0 (0%) +Events: +``` + +本文将逐个描述节点状态的主要内容: + +### Addresses + +依据你集群部署的方式(在哪个云供应商部署,或是在物理机上部署),Addesses 字段可能有所不同。 +* HostName: 在节点命令行界面上执行 `hostname` 命令所获得的值。启动 kubelet 时,可以通过参数 `--hostname-override` 覆盖 +* ExternalIP:通常是节点的外部IP(可以从集群外访问的IP地址,内网地址) +* InternalIP:通常是从节点内部可以访问的 IP 地址(上面的例子中,此字段为空) + +### Conditions + +`Conditions` 描述了节点的状态。Condition的例子有: + +| Node Condition | 描述 | +| ----------------- | ------------------------------------------------------------ | +| OutOfDisk | 如果节点上的空白磁盘空间不够,不能够再添加新的节点时,该字段为 `True`,其他情况为 `False` | +| Ready | 如果节点时健康的且已经就绪可以接受新的 Pod。则节点Ready字段为 `True`。`False`表明了该节点不健康,不能够接受新的 Pod。 | +| MemoryPressure | 如果节点内存紧张,则该字段为 `True`,否则为`False` | +| PIDPressure | 如果节点上进程过多,则该字段为 `True`,否则为 `False` | +| DiskPressure | 如果节点磁盘空间紧张,则该字段为 `True`,否则为 `False` | +| NetworkUnvailable | 如果节点的网络配置有问题,则该字段为 `True`,否则为 `False` | + +Node Condition 以一个 JSON 对象的形式存在。例如,下面的yaml 描述了一个健康状态下节点的 Condition,如下所示: + +```yaml +"conditions": [ + { + "type": "Ready", + "status": "True", + "reason": "KubeletReady", + "message": "kubelet is posting ready status", + "lastHeartbeatTime": "2019-06-05T18:38:35Z", + "lastTransitionTime": "2019-06-05T11:41:27Z" + } +] +``` + +如果 `Ready` 类型Condition 的 `status` 持续为 `Unkown` 或者 `False` 超过 `pod-eviction-timeout`([kube-controller-manager](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/)的参数)所指定的时间,节点控制器(node controller)将对该节点上的所有 Pod 执行删除的调度动作。默认的 `pod-eviction-timeout` 时间是 5 分钟。某些情况下(例如,节点网络故障),apiserver 不能够与节点上的 kubelet 通信,删除 Pod 的指令不能下达到该节点的 kubelet 上,直到 apiserver 与节点的通信重新建立,指令才下达到节点。这意味着,虽然对 Pod 执行了删除的调度指令,但是这些 Pod 可能仍然在失联的节点上运行。 + +在 kubernetes v1.5 以前,节点控制器将从 apiserver 强制删除这些失联节点上的 Pod。在 v1.5 及以后的版本中,节点控制器将不会强制删除这些 Pod,直到已经确认他们已经停止运行为止。您可能会发现失联节点上的 Pod 仍然在运行(在该节点上执行 `docker ps` 命令可查看容器的运行状态),然而 apiserver 中,他们的状态已经变为 `Terminating` 或者 `Unknown`。如果 Kubernetes 不能通过 [cloud-controller-manager](/learning/k8s-bg/component.html#cloud-controller-manager) 判断失联节点是否已经永久从集群中移除(例如,在虚拟机或物理机上自己部署 Kubernetes 的情况),集群管理员需要手工(通过 `kubectl delete node your-node-name` 命令)删除 apiserver 中的节点对象。此时,Kubernetes 将删除该节点上的所有 Pod。 + +在 Kubernetes v1.12 中,[TaintNodesByCondition](/learning/k8s-intermediate/config/taints-toleration/taint-nodes-by-condition.html) 特性进入 beta 阶段,此时 node lifecycle controller 将自动创建该 Condition 对应的 [污点](/learning/k8s-intermediate/config/taints-toleration/)。相应地,调度器在选择合适的节点时,不再关注节点的 Condition,而是检查节点的污点和 Pod 的容忍。 + +### Capacity and Allocatable(容量和可分配量) + +容量和可分配量(Capacity and Allocatable)描述了节点上的可用资源的情况: + +* CPU +* 内存 +* 该节点可调度的最大 pod 数量 + +Capacity 中的字段表示节点上的资源总数,Allocatable 中的字段表示该节点上可分配给普通 Pod 的资源总数。 + +参考 [reserve compute resources](https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable) 可以了解更多关于容量和可分配量的内容。 + +### Info + +描述了节点的基本信息,例如: + +* Linux 内核版本 +* Kubernetes 版本(kubelet 和 kube-proxy 的版本) +* Docker 版本 +* 操作系统名称 + +这些信息由节点上的 kubelet 收集。 diff --git a/learning/k8s-bg/component.md b/learning/k8s-bg/component.md index 5f511d2..cd6c257 100644 --- a/learning/k8s-bg/component.md +++ b/learning/k8s-bg/component.md @@ -1,6 +1,7 @@ --- vssueId: 117 -description: Kubernete教程_Kubernetes组件 +layout: LearningLayout +description: Kubernete教程_Kubernetes组件_Master组件可以运行于集群中的任何机器上。但是,为了简洁性,通常在同一台机器上运行所有的 master 组件,且不在此机器上运行用户的容器 meta: - name: keywords content: Kubernetes 教程,Kubernetes 组件 @@ -115,7 +116,7 @@ Kubernetes 启动容器时,自动将该 DNS 服务器加入到容器的 DNS ### Kuboard -[Kuboard](/install/install-dashboard.html) 也是一款Kubernetes集群的Web管理界面,相较于 Dashboard,Kuboard 强调: +[Kuboard](/install/install-dashboard.html) 是一款基于Kubernetes的微服务管理界面,相较于 Dashboard,Kuboard 强调: * 无需手工编写 YAML 文件 * 微服务参考架构 * 上下文相关的监控 @@ -125,7 +126,7 @@ Kubernetes 启动容器时,自动将该 DNS 服务器加入到容器的 DNS ### ContainerResource Monitoring -[Container Resource Monitoring](https://kubernetes.io/docs/tasks/debug-application-cluster/resource-usage-monitoring/) 将容器的度量指标记录在时间序列数据库中,并提供了 UI 界面查看这些数据 +[Container Resource Monitoring](https://kubernetes.io/docs/tasks/debug-application-cluster/resource-usage-monitoring/) 将容器的度量指标(metrics)记录在时间序列数据库中,并提供了 UI 界面查看这些数据 diff --git a/learning/k8s-bg/what-is-k8s.md b/learning/k8s-bg/what-is-k8s.md index 5cb0fb7..14f6270 100644 --- a/learning/k8s-bg/what-is-k8s.md +++ b/learning/k8s-bg/what-is-k8s.md @@ -1,5 +1,6 @@ --- vssueId: 116 +layout: LearningLayout description: Kubernete教程_Kubernetes介绍_Kubernetes是一个可以移植、可扩展的开源平台,使用声明式的配置,并依据配置信息自动地执行容器化应用程序的管理。 meta: - name: keywords diff --git a/learning/k8s-intermediate/config/sec-ctx/con-kuboard.assets/image-20191005230605496.png b/learning/k8s-intermediate/config/sec-ctx/con-kuboard.assets/image-20191005230605496.png new file mode 100644 index 0000000..f7a48e8 Binary files /dev/null and b/learning/k8s-intermediate/config/sec-ctx/con-kuboard.assets/image-20191005230605496.png differ diff --git a/learning/k8s-intermediate/config/sec-ctx/con-kuboard.md b/learning/k8s-intermediate/config/sec-ctx/con-kuboard.md new file mode 100644 index 0000000..4b8d050 --- /dev/null +++ b/learning/k8s-intermediate/config/sec-ctx/con-kuboard.md @@ -0,0 +1,31 @@ +--- +vssueId: 118 +layout: LearningLayout +description: Kubernetes教程_在Kuboard中为Container容器配置SecurityContext安全上下文。通过 Kuboard,可以直接设定 Deployment、StatefulSet、DaemonSet 等中容器的 securityContext 的内容。在 Kuboard 工作负载编辑器界面中点击 容器组的更多设定 按钮,可查看到容器的 Security Context 设置界面。 +meta: + - name: keywords + content: Kubernetes教程,K8S教程,Security Context,SecurityContext +--- + +# Kuboard中容器的Security Context + +通过 Kuboard,可以直接设定 Deployment、StatefulSet、DaemonSet 等中容器的 securityContext 的内容。在 Kuboard 工作负载编辑器界面中点击 **容器组的更多设定** 按钮,可查看到容器的 Security Context 设置界面,如下图所示: + +![Kubernetes教程_Kuboard中设置容器的SecurityContext](./con-kuboard.assets/image-20191005230605496.png) + + + +上图界面中,各个字段的含义逐个解释如下: + +| 字段名 | 字段类型 | 字段说明 | +| -------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------ | +| privileged | boolean | 以 privileged 模式运行容器。此时容器中的进程本质上等价于宿主节点上的 root 用户。默认值为 `false` | +| 允许扩大特权
allowPrivilegeEscalation | boolean | 该字段控制了进程是否可以获取比父进程更多的特权。直接作用是为容器进程设置 `no_new_privs`标记。当如下情况发生时,该字段始终为 `true`:
1. 以 privileged 模式运行
2. 进程拥有 CAP_SYS_ADMIN 的 Linux capability | +| 文件系统root只读
readOnlyRootFilesystem | boolean | 该容器的文件系统根路径是否为只读。默认为 `false` | +| 非Root
runAsNonRoot | boolean | 如果为 true,则 kubernetes 在运行容器之前将执行检查,以确保容器进程不是以 root 用户(UID为0)运行,否则将不能启动容器;如果此字段不设置或者为 false,则不执行此检查。也可以在Pod的SecurityContext中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | +| 用户
runAsUser | integer | 执行容器 entrypoint 进程的 UID。默认为 docker 引擎的 GID。也可以在Pod的SecurityContext中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | +| 用户组
runAsGroup | integer | 执行容器 entrypoint 进程的 GID。默认为 docker 引擎的 GID。也可以在Pod的SecurityContext中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | +| procMount | string | procMount 代表了容器的 proc mount 的类型。默认值是 `DefaultProcMount`(使用容器引擎的默认值)。该字段需要激活 Kubernetes 的ProcMountType 特性 | +| capabilities |
add: array
drop: array
| 为容器进程 add/drop Linux capabilities。默认使用容器引擎的设定。更多内容请参考 [为容器设置Linux Capabilities](./con-cap.html) | +| seLinuxOptions | | 此字段设定的 SELinux 上下文将被应用到 Pod 中所有容器。如果不指定,容器引擎将为每个容器分配一个随机的 SELinux 上下文。也可以在Pod的SecurityContext中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | + diff --git a/learning/k8s-intermediate/config/sec-ctx/pod-kuboard.md b/learning/k8s-intermediate/config/sec-ctx/pod-kuboard.md index eda22a6..d4f1fc2 100644 --- a/learning/k8s-intermediate/config/sec-ctx/pod-kuboard.md +++ b/learning/k8s-intermediate/config/sec-ctx/pod-kuboard.md @@ -17,15 +17,15 @@ meta: 上图界面中,各个字段的含义逐个解释如下: -| 字段名 | 字段类型 | 字段说明 | -| -------------- | -------- | ------------------------------------------------------------ | -| 非Root | boolean | 如果为 true,则 kubernetes 在运行容器之前将执行检查,以确保容器进程不是以 root 用户(UID为0)运行,否则将不能启动容器;如果此字段不设置或者为 false,则不执行此检查。该字段也可以在容器的 securityContext 中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | -| 用户 | integer | 执行容器 entrypoint 进程的 UID。默认为镜像元数据中定义的用户(dockerfile 中通过 USER 指令指定)。该字段也可以在容器的 securityContext 中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | -| 用户组 | integer | 执行容器 entrypoint 进程的 GID。默认为 docker 引擎的 GID。该字段也可以在容器的 securityContext 中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | -| fsGroup | integer | 一个特殊的补充用户组,将被应用到 Pod 中所有容器。某些类型的数据卷允许 Kubelete 修改数据卷的 ownership:
1. 修改后的 GID 取值来自于 fsGroup
2. setgid 标记位被设为 1(此时,数据卷中新创建的文件 owner 为 fsGroup)
3. permission 标记将与 `rw-rw----` 执行或运算
如果该字段不设置,kubelete 将不会修改数据卷的 ownership 和 permission | -| 补充用户组 | integer | 该列表中的用户组将被作为容器的主 GID 的补充,添加到 Pod 中容器的 enrtypoint 进程。可以不设置。 | -| seLinuxOptions | Object | 此字段设定的 SELinux 上下文将被应用到 Pod 中所有容器。如果不指定,容器引擎将为每个容器分配一个随机的 SELinux 上下文。该字段也可以在容器的 securityContext 中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | -| sysctls | Array | 该列表中的所有 sysctl 将被应用到 Pod 中的容器。如果定义了容器引擎不支持的 sysctl,Pod 启动将会失败 | +| 字段名 |
字段类型
| 字段说明 | +| ---------------------------------- | ---------------------------------------- | ------------------------------------------------------------ | +| 非Root
runAsNonRoot | boolean | 如果为 true,则 kubernetes 在运行容器之前将执行检查,以确保容器进程不是以 root 用户(UID为0)运行,否则将不能启动容器;如果此字段不设置或者为 false,则不执行此检查。该字段也可以在容器的 securityContext 中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | +| 用户
runAsUser | integer | 执行容器 entrypoint 进程的 UID。默认为镜像元数据中定义的用户(dockerfile 中通过 USER 指令指定)。该字段也可以在容器的 securityContext 中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | +| 用户组
runAsGroup | integer | 执行容器 entrypoint 进程的 GID。默认为 docker 引擎的 GID。该字段也可以在容器的 securityContext 中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | +| fsGroup | integer | 一个特殊的补充用户组,将被应用到 Pod 中所有容器。某些类型的数据卷允许 Kubelete 修改数据卷的 ownership:
1. 修改后的 GID 取值来自于 fsGroup
2. setgid 标记位被设为 1(此时,数据卷中新创建的文件 owner 为 fsGroup)
3. permission 标记将与 `rw-rw----` 执行或运算
如果该字段不设置,kubelete 将不会修改数据卷的 ownership 和 permission | +| 补充用户组
supplementalGroups | integer | 该列表中的用户组将被作为容器的主 GID 的补充,添加到 Pod 中容器的 enrtypoint 进程。可以不设置。 | +| seLinuxOptions | Object | 此字段设定的 SELinux 上下文将被应用到 Pod 中所有容器。如果不指定,容器引擎将为每个容器分配一个随机的 SELinux 上下文。该字段也可以在容器的 securityContext 中设定,如果 Pod 和容器的 securityContext 中都设定了这个字段,则对该容器来说以容器中的设置为准。 | +| sysctls | Array | 该列表中的所有 sysctl 将被应用到 Pod 中的容器。如果定义了容器引擎不支持的 sysctl,Pod 启动将会失败 | 关于 SecurityContex 在运行时怎么工作,请参考: * [为Pod设置Security Context](./pod.html) diff --git a/learning/k8s-intermediate/config/taints-toleration/taint-based-evictions.md b/learning/k8s-intermediate/config/taints-toleration/taint-based-evictions.md index 56640a7..fffb6e4 100644 --- a/learning/k8s-intermediate/config/taints-toleration/taint-based-evictions.md +++ b/learning/k8s-intermediate/config/taints-toleration/taint-based-evictions.md @@ -10,7 +10,7 @@ meta: # 基于污点的驱逐(TaintBasedEviction) -在前面的章节中,我们描述了 [NoExecute](http://localhost:8080/learning/k8s-intermediate/config/taints-toleration/#%E6%B1%A1%E7%82%B9%E4%B8%8E%E5%AE%B9%E5%BF%8D%E7%9A%84%E5%8C%B9%E9%85%8D) 的污点效果,该效果将对已经运行在节点上的 Pod 施加如下影响: +在前面的章节中,我们描述了 [NoExecute](/learning/k8s-intermediate/config/taints-toleration/#污点与容忍的匹配) 的污点效果,该效果将对已经运行在节点上的 Pod 施加如下影响: * 不容忍该污点的 Pod 将立刻被驱逐 * 容忍该污点的 Pod 在未指定 `tolerationSeconds` 的情况下,将继续在该节点上运行 * 容忍该污点的 Pod 在指定了 `tolerationSeconds` 的情况下,将在指定时间超过时从节点上驱逐 diff --git a/package-lock.json b/package-lock.json index 49b6dcf..39503a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11505,6 +11505,11 @@ "resolved": "https://registry.npm.taobao.org/slash/download/slash-2.0.0.tgz", "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=" }, + "smoothscroll-polyfill": { + "version": "0.4.4", + "resolved": "https://registry.npm.taobao.org/smoothscroll-polyfill/download/smoothscroll-polyfill-0.4.4.tgz", + "integrity": "sha1-OiWRMdxpMObKgAA+HLA7YDtpq/g=" + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz", @@ -12884,6 +12889,14 @@ "sitemap": "^2.0.1" } }, + "vuepress-plugin-smooth-scroll": { + "version": "0.0.4", + "resolved": "https://registry.npm.taobao.org/vuepress-plugin-smooth-scroll/download/vuepress-plugin-smooth-scroll-0.0.4.tgz", + "integrity": "sha1-ZEcilHbmBO+L1usqVtN3xpdKPY4=", + "requires": { + "smoothscroll-polyfill": "^0.4.4" + } + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npm.taobao.org/watchpack/download/watchpack-1.6.0.tgz?cache=0&sync_timestamp=1562782917067&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwatchpack%2Fdownload%2Fwatchpack-1.6.0.tgz", diff --git a/package.json b/package.json index 1e5172b..9787e28 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "esm": "^3.2.25", "npm": "^6.11.3", "reduce-css-calc": "^2.1.6", - "vuepress": "^1.1.0" + "vuepress": "^1.1.0", + "vuepress-plugin-smooth-scroll": "0.0.4" } }