kubernetes-tips

kubernetes-tips

Scroll Down

1、RS历史版本

Deployment 中可以设置.spec.revisionHistoryLimit字段来指定保留此Deployment的多少个旧有ReplicaSet。其余的RS将在后台被垃圾回收。默认情况下。此值为10

显式将此字段设置为 0 将导致 Deployment 的所有历史记录被清空,因此 Deployment 将无法回滚

2、删除Evited的Pod

# kubectl -n kube-system  get pods | grep Evicted |awk '{print$1}'|xargs kubectl -n kube-system delete pods

3、kube-proxy 是 ipvs/iptables?

个人见解

# 可以通过查看kube-proxy使用configmap的字段“mode”
kubectl get configmap -n kube-system
kubectl describe configmap -n kube-system kube-proxy

kubeproxy_configmap.png

4、kubernetes的服务发现

参考来源

① kubernetes的svc 对后端pod的负载均衡是4层的轮询,所以同一个连接里发起的所有请求都会进入同一个 Pod。因为在 4 层工作,所以对于 7 层的 HTTP 头或者 Cookie 之类的东西是无法感知的
② Kubernetes 使用 DNS 作为服务注册表

注册过程大致如下:

① 向 API Server 用 POST 方式提交一个新的 Service 定义;
② 这个请求需要经过认证、鉴权以及其它的准入策略检查过程之后才会放行;
③ Service 得到一个 ClusterIP(虚拟 IP 地址),并保存到集群数据仓库;
④ 在集群范围内传播 Service 配置;
⑤ 集群 DNS 服务得知该 Service 的创建,据此创建必要的 DNS A 记录。
上面过程中,第 5 个步骤是关键环节。集群 DNS 使用的是 CoreDNS,以 Kubernetes 原生应用的形式运行。CoreDNS 实现了一个控制器,会对 API Server 进行监听,一旦发现有新建的 Service 对象,就创建一个从 Service 名称映射到 ClusterIP 的域名记录。这样 Service 就不必自行向 DNS 进行注册,CoreDNS 控制器会关注新创建的 Service 对象,并实现后续的 DNS 过程。

DNS 中注册的名称就是 metadata.name,而 ClusterIP 则由 Kubernetes 自行分配。
svcdiscovery1.jpg

要使用服务发现功能,每个 Pod 都需要知道集群 DNS 的位置才能使用它。因此每个 Pod 中的每个容器的 /etc/resolv.conf 文件都被配置为使用集群 DNS 进行解析。

每个新 Service 对象的配置,其中包含它的 ClusterIP 以及 Endpoints 对象(其中包含健康 Pod 的列表),都会被发送给 每个节点上的 kube-proxy 进程。kube-proxy 会创建 iptables 或者 IPVS 规则,告知节点捕获目标为 Service ClusterIP 的流量,并根据 Endpoints 对象的内容转发给对应的 Pod。
也就是说每次节点内核处理到目标为 Service 网络的数据包时,都会对数据包的 Header 进行改写,把目标 IP 改为 Service Endpoints 对象中的健康 Pod 的 IP。

服务发现总结

创建新的 Service 对象时,会得到一个虚拟 IP,被称为 ClusterIP。服务名及其 ClusterIP 被自动注册到集群 DNS 中,并且会创建相关的 Endpoints 对象用于保存符合标签条件的健康 Pod 的列表,Service 对象会向列表中的 Pod 转发流量。
与此同时集群中所有节点都会配置相应的 iptables/IPVS 规则,监听目标为 ClusterIP 的流量并转发给真实的 Pod IP。这个过程如下图所示:

svcdiscovery2.jpg

一个 Pod 需要用 Service 连接其它 Pod。首先向集群 DNS 发出查询,把 Service 名称解析为 ClusterIP,然后把流量发送给位于 Service 网络的 ClusterIP 上。然而没有到 Service 网络的路由,所以 Pod 把流量发送给它的缺省网关。这一行为导致流量被转发给 Pod 所在节点的网卡,然后是节点的缺省网关。这个操作中,节点的内核修改了数据包 Header 中的目标 IP,使其转向健康的 Pod。

svcdiscovery3.jpg

5、将configmap挂载成pod内的文件

现在有一个configmap:

configmap_mount_pod_file_1.png

这个configmap的键名为文件名,键值是文件内容。需求是把这个configmap以文件形式挂载到容器中的特定目录下,deploy yaml部分如下:

configmap_mount_pod_file_2.png

6、重启deployment小技巧

参考来源

# 修改<deployment-name>、<container-name>、<namespace>
kubectl patch -n <namespace> deployment <deployment-name> -p '{"spec":{"template":{"spec":{"containers":[{"name":"<container-name>","env":[{"name":"RESTART_","value":"'$(date +%s)'"}]}]}}}}'

有时候我们会需要重启Deployment,原因可能是:

1、docker image使用的是latest tag,这个latest在docker image registry已经更新了,我们需要重启deployment来使用新的latest
2、Pod运行缓慢但是还活着,就是想重启它一下
3、ConfigMap/Secret变更了,想重启一下应用新配置

当Deployment spec没有发生任何变化,即使你kubectl apply -f deployment-spec.yaml也是没用的,因为K8S会认为你这个没有变化就什么都不做了。

基本思路就是给Container添加一个无关紧要的环境变量,这个环境变量的值就是时间戳,而这个时间戳则是每次执行上述命令的系统当前时间。这样一来对于K8S来讲这个Deployment spec就变化了,就可以像Updating a deployment一样,重启Pod了

7、Configmap

Configmap可以挂载到容器中的Env上,此种形式下,更新Configmap后,使用该 ConfigMap 挂载的 Env 不会同步更新。

Configmap可以以volumes的形式挂载到容器中的文件,此种形式下,更新Configmap后,使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新.

不管基于哪种形式使用了ConfigMap挂载的配置,更新 ConfigMap 目前都不会触发相关 Pod 的滚动更新,都需要通过滚动更新Pod的方式来强制重新挂载ConfigMap