一、学 GO 语言
Kubernetes是基于 GO 编写的,所有的组件都是基于 GO 编写的,kubernetes甚至使用GO编写了一个客户端。学习使用 GO 语言编写的 Kubernetes 客户端并在 Kubernetes 中使用它,这是我对所以使用 Kubernetes 集群的朋友提出的最大的建议。
二、使用探针来检测应用的状态
在Kubernetes中支持配置探针。kubelet使用探针来确定pod和应用程序是否健康。这里提供了两种类型来实现这一功能,Readiness探针和Liveiness探针。Readiness探针用于确定容器何时准备好接收流量。Liveiness探针用于确定容器是健康的还是需要重新启动。在deployment 的yaml中,可以直接定义Readiness 探针和Liveiness探针,还可以设置超时、重试和延迟等参数。
三、充分利用Label标签
标签是Kubernetes的基础配置之一。它允许进群内资源与资源之间松散耦合,还允许基于标签进行查询。你甚至可以使用Kubernetes go客户端,根据标签查看事件。你几乎可以使用标签做任何事情,一个典型的例子是是同一个集群中存在多个环境。假设开发和QA使用相同的集群。这意味着你的集群可能同时进行QA和开发。要以一种简单的方式实现这一点,你必须使用服务对象,一个服务对象在app上执行标签select: app-a以及environment: dev,另一个服务对象在app上打上:app-a标签,但将环境从dev切换到QA。这将为您提供两个相同的应用程序,每个应用程序具有不同的端点,允许同时进行测试。
四、随时记得回收废弃的资源
Kubernetes是一个非常强大的系统,但是就像任何系统一样,它也会出现阻塞。只有一个不连接其他任何服务的服务才不会让系统陷入停滞。当kubernetes规模较小时,几台或者几十台,可能不会有任何问题。但如果把服务扩大到上万,kubelet就会可是出现阻塞。因为Kubelet不仅会对你发出的指令进行校验,同时还要做内部检查。因此,切记,从现在开始,养成习惯。如果你需要删除deployment(或相关的任何内容),请确保用它清理了所有其他内容,比如service,volume等等,避免日后影响kubelet的查询效率。
五、充分利用PodDisruptionBudget控制器
如何保证在kubernetes集群中的应用程序总能正常运行?答案是使用PodDisruptionBudget控制器。在进行kubectl drain操作时,kubernetes会根据PodDisruptionBudget控制器判断应用POD集群数量,进而保证在业务不中断或业务SLA不降级的情况下进行应用POD销毁。PDB(PodDisruptionBudget)应该放在每个拥有一个以上实例的deployment上。我们可以使用简单yaml为集群创建PDB,并使用标签选择器确定PDB应该作用在哪些带有标签的资源上。注意:PDB只考虑主动中断,硬件故障之类的情况不在PDB考虑范围内。PDB可以参考如下例子:
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: app-a-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: app-a
在众多配置中,我们最需要关注两个选项是matchlabel和minAvailable部分。匹配标签是kubernetes查看部署是否附加到PDB。例如:如果我有一个带有标签app: app-a的部署和一个带有标签app: app-b的部署,那么示例PDB将只应用于第一个部署。minAvailable会在kubernetes在执行类似 kubectl drain的操作时起作用。假设app-a正在节点1上运行,如果在节点1上执行drain,那么它将只驱逐app-a,即当前至少有2个app在运行。这让你可以控制在给定时间需要运行多少实例。
六、使用Bash完成kubectl命令
这可能是最简单也是使用Kubernetes时最有帮助的方法之一。要添加自动完成(如果使用bash),只需运行以下命令:
echo “source <(kubectl completion bash)” >> ~/.bashrc
这将在.bashrc中添加自动完成功能,这样无论何时打开shell,它都会启用它。你将会发现使用自动补全功能对于输入长指令来说是尤为方便的,尤其是当需要指定命名空间时。
七、向命名空间添加默认内存限制和cpu限制
人们总会犯错,这是常有的事。如果有人编写了一个应用程序,比方说,每秒打开一个数据库的连接,但是从来没有关闭它,这时就会导致在集群上的应用程序中出现内存泄漏。如果将它们部署到没有设置限制的集群中,则可能导致节点崩溃。为了防止这种情况,Kubernetes允许根据每个命名空间设置默认限制。要做到这一点,只需创建一个yaml来限制范围并将其应用于这个命名空间。下面是yaml的一个例子:
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
spec:
limits:
- default:
memory: 512Mi
defaultRequest:
memory: 256Mi
type: Container
八、用Kubelet辅助清理docker镜像
kubelet默认情况下已经做到了这一点。如果在启动kubelet时没有设置任何标志,那么当var/lib/docker达到90%的容量时,它将启动垃圾收集。这一功能非常贴心,但请注意,kubelet并没有为node节点设置默认阈值(在Kubernetes 1.7之前)。试想这种情况,你的/var/lib/docker可能只占用了50%的磁盘空间,但此时全部的物理机磁盘空间已经被占满。这会给你的容器服务带来很多问题。如果您目前正在使用的kubelet版本是1.4-1.6,那么你必须显式为kubelet添加如下标志。
--eviction-hard=memory.available<100Mi,nodefs.available<10%,nodefs.inodesFree<5%
这些配置在1.7或更高版本时是默认配置项。1.6版本默认情况下不监视 node 节点的资源利用率,因此添加该标志将解决这个问题。
九、Minikube ——迷你但功能强大
Minikube绝对是本地运行Kubernetes集群最简单的方法了。一旦一切都安装好了,简单的命令就能运行它。
minikube start
这时我们将在本地运行一个 K8S 集群。当你想要在本地构建一个应用程序并在本地运行它时,这是有个技巧需要注意。如果你没有运行其他命令,当你执行docker build时,仍然会在物理机上构建一个映像。要让你的docker build将镜像push到本地kubernetes集群,你需要使用以下命令:
eval $(minikube docker-env)
这能让你在本地kubernetes集群上构建应用程序。
十、不要把kubectl权限开放给所有人
这可能说起来很简单,但是当多个团队部署应用到一个 kubernetes 集群时,情况就可能变得很复杂。切记不要把 kubectl 权限开放给每个人。个人建议是,根据命名空间来区分隔离每个团队,然后使用RBAC策略只允许各自团队访问各自的命名空间。如果我们把kubectl权限开放给每个人,那么在pod级上进行读取、创建和删除访问时,可能让人抓狂,因为误操作的情况会经常发生。为此,我们应该只允许管理员有权访问,从而将管理集群和部署集群的人员权限区分开。