1.1 Node Controller 简介
每个 Node 上都有一个 kubelet 进程,当启动集群时,kubelet 会通过 API Server 注册自身所在 Node 节点的信息(kubelet 使用参数 --register-node=true 设置),这些信息包括节点健康状况、节点资源、节点名称、节点地址信息、操作系统版本、Docker 版本、kubelet 版本等。然后定时向 API Server 汇报这些信息并更新到 ETCD 中。
节点健康状况包括 3 种类型:就绪(True)、未就绪(False)、未知(Unknown)。
Node Controller 在 Node 的生命周期中主要有 3 个作用:
- 注册时分配 CIDR block:如果 Controller Manager 设置了
--cluster-cidr参数,则为每个 Node 都配置spec.PodCIDR。 - 更新 nodes 列表:如果云服务商提供了可用机器列表,Node Controller 需要及时更新内部的 nodes 列表,以保证两个列表同步。在云环境中,当一个 Node 不健康时,Node Controller 会询问云服务商 node 所在的虚拟机是否可用,如果不可用,Node Controller 会将该 node 从 nodes 列表中删除。
- 监控 nodes 的健康情况:Node Controller 负责在 node 无法访问时(即:Node Controller 因为某些原因没有收到心跳,比如 node 宕机)将它的 NodeStatus 从 NodeReady 状态更新为 ConditionUnknown,如果后续该 node 持续不可访问,Node Controller 会删除 node 上的所有 pods。使用参数
--node-monitor-period设置检查 node 状态的间隔时长。
Node 的隔离与恢复
当硬件需要升级或是维护时,我们需要暂时将某些 Node 进行隔离,让它脱离 Kubernetes 集群的调度范围。
新建 unschedule_node.yaml 文件,并向其中写入如下代码:
apiVersion: v1
kind: Node
metadata:
name: kubesphere02
spec:
unschedulable: true
然后执行 kubectl replace 命令对 Node 的状态进行修改:
$ kubectl replace -f unschedule_node.yaml
node/kubesphere02 replaced
现在查看 Node 的状态:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kubesphere01 Ready master 79d v1.16.9
kubesphere02 Ready,SchedulingDisabled <none> 79d v1.16.9
kubesphere03 Ready <none> 79d v1.16.9
可以发现 status 中增加了一项 SchedulingDisabled。那么后续如果再创建 Pod,就不会再调度到 kubesphere02 这个节点上了。但是 kubesphere02 这个节点脱离调度范围,运行在其上的 Pod 不会自动停止,需要手动停止。
也可以使用命令实现将 Node 进行隔离和恢复调度的操作:
# 隔离
$ kubectl cordon kubesphere02
node/kubesphere02 already cordoned
# 恢复调度
$ kubectl uncordon kubesphere02
node/kubesphere02 uncordoned
Node 的扩容
在实际的生产过程中,可能会遇到服务器容量不足的情况,这个时候需要购买新的服务器,并将应用系统进行水平扩展完成对系统的扩容。
具体的流程如下:
在新的 Node 节点上安装 Docker、kubelet 和 kube-proxy 服务,配置 kubelet 和 kube-proxy 启动参数,将 Master URL 指定为当前 Kubernetes 集群的 Master 地址,然后启动这些服务。kubelet 拥有默认的自动注册机制,Kubernetes Master 接受了注册之后,会自动把新的 Node 节点纳入集群的调度范围之内。
2.1 Namespace Controller 简介
Namespace 类似于 Linux 系统中用户的概念,主要用于实现多租户的资源隔离,将资源对象分配到不同的命名空间中,形成了逻辑上分组的不同项目、小组或用户组,不同的分组在共享集群资源时也能被分别管理。
Namespace 下的资源对象有很多,比如:Pod、Service、ReplicationController、ReplicaSet、Deployment 等;但是有些资源对象是不属于命名空间下的,比如:Node、Persistent Volume、Namespace 等。需要注意的是:在一个 Namespace 下,资源对象的名称必须唯一。
而 Namespace Controller 的主要作用是读取 Namespace 下的资源对象信息,并执行删除 Namespace 的操作。具体过程为:
用户通过 API Server 创建新的 Namespace,将这些数据保存到 ETCD 中,Namespace Controller 定期通过 API Server 读取这些 Namespace 的信息。如果 Namespace 被 API 标识为优雅删除,那么该命名空间的状态会变为 Terminating,并将状态变更存储到 ETCD 中,Namespace Controller 会删除该命名空间下的所有资源对象;Admission Controller 会阻止继续为该 Namespace 创建新的资源对象,Namespace Controller 对该 Namespace 执行 finalize 操作删除 spec.finalizers 域中的信息,最后 Namespace Controller 通过 API Server 删除该 Namespace 资源对象。
上面介绍的就是 Namespace Controller 运行的具体过程,而在平时更多接触到的是与命名空间相关的一些操作。
创建 Namespace
比如现在有两个环境:开发环境和线上产品环境,开发环境为了实现敏捷开发在集群中可能会不断的创建、修改、删除各种资源对象,而线上产品环境需要保持环境中资源的正常运行、不被误删。
执行如下命令分别创建两个命名空间:
# 创建开发者环境
$ kubectl create namespace dev
namespace/dev created
# 创建线上产品环境
$ kubectl create namespace prod
namespace/prod created
创建成功后查看系统中的命名空间:
# 当 STATUS 为 Active 表示这个命名空间在使用中;如果 STATUS 为 Terminating,则表示这个命名空间正在被删除,不会再创建其它的资源对象了
$ kubectl get namespace
NAME STATUS AGE
default Active 79d
dev Active 65s
ingress-nginx Active 18h
kube-node-lease Active 79d
kube-public Active 79d
kube-system Active 79d
prod Active 59s
default 命名空间是默认的,如果不指定命名空间,默认创建的所有资源对象都在这个命名空间下;kube-system 命名空间运行着 kubernetes 系统创建的资源对象。kube-public 命名空间中的资源可以被所有人访问(包括未认证用户)。
如果要查看命名空间的详细信息:
$ kubectl describe namespace default
Name: default
Labels: kubesphere.io/workspace=system-workspace
Annotations: openpitrix_runtime: runtime-Gv3l8x5mp4Mm
Status: Active
No resource quota.
No resource limits.
2.2 定义 Context(运行环境)
Context(运行环境)在有的地方又称为:上下文。即:命令运行的环境。
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kubernetes-admin@kubernetes kubernetes kubernetes-admin kube-system
新创建一个集群名为 kubernetes-cluster,对于它们的配置都会写入 ~/.kube/config 文件中。
接着为这两个工作组分别定义一个 Context(运行环境),当运行环境和命名空间关联起来的时候,这个运行环境就只属于该命名空间下的了。
执行如下命令:
# 新配置一个集群(不使用默认集群 kubernetes),名为 kubernetes-cluster,并配置 server
$ kubectl config set-cluster kubernetes-cluster --server=https://192.168.0.31:6443
Cluster "kubernetes-cluster" set.
# 为 kubernetes-cluster 集群定义通过 dev 用户访问 dev 命名空间的运行环境名为 ctx-dev
$ kubectl config set-context ctx-dev --namespace=dev --cluster=kubernetes-cluster --user=dev
Context "ctx-dev" created.
# 为 kubernetes-cluster 集群定义通过 prod 用户访问 prod 命名空间的运行环境名为 ctx-prod
$ kubectl config set-context ctx-prod --namespace=prod --cluster=kubernetes-cluster --user=prod
Context "ctx-prod" created.
再查看:
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
ctx-dev kubernetes-cluster dev dev
ctx-prod kubernetes-cluster prod prod
* kubernetes-admin@kubernetes kubernetes kubernetes-admin kube-system
这样就可以清楚的看到:对于集群 kubernetes-cluster 绑定了不同的命名空间 dev 和 prod,运行环境(上下文)分别命名为 ctx-dev 和 ctx-prod。
2.3 设置工作组在特定 Context 环境中工作
可以使用 kubectl config use-context <context_name> 来设置当前的运行环境。
首先将运行环境设置为 ctx-dev,也就是开发环境,之后的所有操作就需要在 dev 命名空间下完成:
$ kubectl config use-context ctx-dev
Switched to context "ctx-dev".
# 可以看到当前环境已经切换
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* ctx-dev kubernetes-cluster dev dev
ctx-prod kubernetes-cluster prod prod
kubernetes-admin@kubernetes kubernetes kubernetes-admin kube-system
$ cat ~/.kube/config | grep current-context
current-context: ctx-dev
现在以 nginx Deployment 为例创建两个 Pod,新建 nginx-deployment.yaml 文件,并向其中写入如下代码:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80 # 指定开放 80 端口
执行如下命令进行创建:
$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx created
查看创建好的 Pod:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-687548bb8c-bl7kt 1/1 Running 0 33s
nginx-687548bb8c-fxwxq 1/1 Running 0 33s
可以看到容器被正确的创建并运行起来了,当前是 ctx-dev 的环境,在这个环境中执行的操作并不会影响 ctx-prod 的工作,现在切换到线上产品环境:
$ kubectl config use-context ctx-prod
Switched to context "ctx-prod".
可以查看 Deployment 和 Pod:
$ kubectl get deploy
No resources found.
$ kubectl get pods
No resources found.
结果为空也就证明了两个环境是被隔离的,彼此不会互相影响。
现在为线上产品环境也使用 YAML 文件创建两个 nginx Pod 进行验证:
$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-687548bb8c-9r5dk 1/1 Running 0 5s
nginx-687548bb8c-zwfff 1/1 Running 0 5s
可以看到两个 Pod 正常的运行在当前的线上生产环境中。
2.4 删除 Namespace
删除命名空间:
$ kubectl delete namespace dev
namespace "dev" deleted
$ kubectl delete namespace prod
namespace "prod" deleted
注意:如果删除命名空间,将会自动删除该命名空间下的所有资源。default 和 kube-system 命名空间不能删除。
最后手动将运行环境(上下文)切换回原来的:
# 切换回 kubernetes-admin@kubernetes 环境
$ kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
# 检查当前环境名称
$ kubectl config current-context
kubernetes-admin@kubernetes
评论区