kubectl
1 | # 使用原始 URL 获取资源信息 |
判断 deploy ready
1 | kubectl rollout status deployment/<deployment-name> |
列出命名空间下所有资源对象
1 | kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found -n default |
Patch 更新的三种操作
如下为 kubectl patch 命令更新资源的基本形式,其中 type 有三种 json/merge/strategic:
1 | kubectl patch xxxx --type xxxx --patch xxxx |
标准的 json patch,Content-Type: application/json-patch+json:
1 | kubectl patch deployments patch-demo --type json --patch '[{"op":"replace", "path":"/spec/replicas", "value":4}]' |
标准的 json merge patch,Content-Type: application/merge-json-patch+json,执行局部替换:
1 | $ cat prometheus-patch.yaml |
JSON strategic merge patch,增量形式更新对象,默认策略是执行替换,实际策略与属性的标签有关:
1 | $ cat patch-file-containers.yaml |
taint
1 | # 去除所有节点 mater taint 使之可调度 |
toleration
1 | # 容忍所有 |
etcd
- 命令行读写
1 | export ETCDCTL_API=3 |
- 备份
1 | etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key snapshot save etcd-snapshot.db |
- 磁盘读写速度过慢造成的故障
如果 etcd pod 的 log 中会存在大量的类似 “etcdserver: read-only range request “key:…” with result “…” took too long (…) to execute” 的报错,大概率是磁盘损坏造成的读写速度过慢导致的,etcd 的数据存储在 /var/lib/etcd 目录下。
- 删除节点
1 | etcdctl member list |
- check cluster health
1 | etcdctl endpoint health |
- etcd 故障恢复
注意:对于断电或系统意外崩溃的情况可尝试重启 etcd ,如果重启无法解决再使用备份进行恢复。
参考:https://blog.csdn.net/dazuiba008/article/details/94595679
drain node
1 | # 不加 --ignore-daemonsets 会因为节点上部署有 daemonset 管理的 Pod 而中止 |
nodeName/nodeSelector/Affinity
直接指定 nodeName 后 Pod 将被视为已调度而不再经过调度器进行调度;nodeSelector 通过节点标签来指定 Pod 调度到相应节点上去,是较为简单的一种方式;Affinity 支持逻辑表达式实现更复杂的调度逻辑,且可设置不具强制性的软亲和,还可以设置 Pod 之间的亲和与反亲和特性。
逻辑上的隔离
可通过配置限制 kubelet 在启动时设置节点的某些具有特殊前缀的标签,例如 node-role.kubernetes.io/master, node-restriction.kubernetes.io/
等,这些标签只能在节点加入集群后由具有集群管理员权限的用户添加上去,配合 nodeSelector/Affinity
可以实现 Pod 在逻辑上的一种隔离,将具有不同安全等级要求的 Pod 调度到不同的节点上去。
节点状态和 Taint
当节点 Condition 中的最后一项即 Type 为 Ready 这一项,其 Status 值为 False 时,controller-manager 中的 node-controller 会自动为节点添加 key 为 node.kubernetes.io/not-ready 的 taint;当其 Status 值为 Unknown 时,自动添加 key 为 node.kubernetes.io/unreachable 的 taint。当 taint effect 为 NoExecute,会驱逐运行在问题节点上的 Pod。参考:https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/。
Kubernetes-go-client
- 更新 api 对象的两种方式
1 | import ( |
证书
- 为 Ingress Host 生成自签名证书
- 简易方法
参考:https://kubernetes.github.io/ingress-nginx/user-guide/tls/
1 | KEY_FILE=dashboard_key |
- 定制
参考: https://mritd.me/2017/03/04/how-to-use-nginx-ingress/
1 | # 生成 CA 自签证书 , 也可以直接使用 /etc/kubernetes/pki/ 下的 CA 证书 |
- 查看证书内容
1 | openssl x509 -in ca.crt -text -noout |
- 检查证书过期时间
1 | kubeadm alpha certs check-expiration |
Kubeadm
- kubeadm join … -v 10
kubeadm 添加第二个 master 节点时出现以下错误:
1 | I0724 10:27:10.396559 31977 token.go:141] [discovery] Requesting info from "https://192.168.2.65:6445" again to validate TLS against the pinned public key |
错误表明 kubeadm 已经成功从 kube-public 命名空间下的 cluster-info confgimap 中获取到了集群信息,然后在验证集群证书的有效性时出错。x509: certificate has expired or is not yet valid
一般是由于系统时间错误导致,可以先用 date 命令确定本地时间是否正确。如果本地时间错误,可以尝试使用 ntp 同步系统时间。
1 | ntpdate cn.pool.ntp.org |
- kubeadm 部署时 config 文件
参考:https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2,kubelet 自定义配置参考:https://godoc.org/k8s.io/kubelet/config/v1beta1#KubeletConfiguration。一个需要注意的地方是
一个单 master 节点集群配置参考,需要注意的是虽然在下面的配置中已经设置了 failSwapOn 为 false,但是 kubeadm 并不会去检测该配置,仍然会报错,不过该报错可以被忽略,因为这个设置随后确实会被添加到 kubelet 的配置中并生效,因此 init 时执行 sudo kubeadm init --config kubeadm.yml --ignore-preflight-errors=all
即可:
1 | apiVersion: kubeadm.k8s.io/v1beta2 |
- 内核配置参考
1 | [xyc-pc ~]# cat /etc/modules-load.d/ipvs.conf |
Helm
- helm init 使用 azure 镜像
1 | helm init --stable-repo-url http://mirror.azure.cn/kubernetes/charts/ |
- 从模板生成本地文件
1 | mkdir yamls |
- 拉取压缩文件到本地
1 | helm fetch ucloud/uk8s-etcd-backup |
- 制作 chart
1 | ➜ tree uk8s-etcd-backup |
添加自定义 DNS 记录
1 | [root@10-8-62-148 ~]# kubectl get cm -n kube-system coredns -oyaml |
向容器添加 hosts 记录
1 | apiVersion: v1 |
ingress-nginx
- 为转向上游的请求添加 header:
1 | apiVersion: extensions/v1beta1 |
- nginx 原样传递编码过的 URL
1 | map '' $seed_uri { |
- 自定义 timeout
1 | apiVersion: extensions/v1beta1 |
- 后端服务需要使用 HTTPS 访问
1 | nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" |
- 透传 TLS 握手
1 | nginx.ingress.kubernetes.io/ssl-passthrough: "true" |
- 实现泛域名解析
借助 lua 脚本实现,参考:https://www.bookstack.cn/read/kubernetes-practice-guide/best-practice-wildcard-domain-forward.md
CronJob 与 Job
建议设置 startingDeadlineSeconds 值以防止从最后一次调度到当前时间错过的调度次数超过 100 导致不再进行调度(使用 etcd 备份数据恢复集群时可能出现这种情况),参考:https://www.jianshu.com/p/3e3b18414e45。
job.spec.ttlSecondsAfterFinished 参数有三种选项:不设置,则 Job 不会被自动删除;设置为 0 ,则在 Job 运行完成后立即自动删除;设置为非零值,则在一定时间后自动删除。
cronjob 则通过 cronjob.spec.failedJobsHistoryLimit (默认值为 1 ) 和 cronjob.spec.successfulJobsHistoryLimit (默认值为 3 ) 来控制保存的 Job 数量。
job.spec.template.spec.restartPolicy 设置的是 Pod 的重启策略,在 Job 这种一次性任务的场景中,应当设置为 OnFailure 或者 Never,在 Deployment 场景中应当保持默认值 Always。
job.spec.backoffLimit 设置的次数指的是 Pod 运行失败后,尝试重新创建 Pod 的次数,不包括第一次运行。例如,设置 backoffLimit 为 2 ,则该 job 相关的 Pod 最多会重试三次(通过依次创建 3 个不同的 Pod 实现)。这有别于 job.spec.template.spec.restartPolicy 参数,restartPolicy 是针对同一个 Pod 不停重启重试,而 job.spec.backoffLimit 则是尝试创建新的 Pod。
field-selector 和 labels-selector
字段选择器:
1 | kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always |
标签选择器:
1 | kubectl get pods -l environment=production,tier=frontend |
使用 subPath 挂载 Volume
1 | apiVersion: apps/v1 |
创建并使用 imagePullSecrets
1 | // 创建 secret |
sealos 部署 Kubernetes
开发测试可以使用 sealos 这个工具,通过离线安装包部署 Kubernetes,省心实用,但是作者在改过的 Kubeadm 代码里夹杂了一些私货令人不喜。
离线安装包下载链接
添加 master 节点
1 | // 先安装好 docker, 参见:https://docs.docker.com/install/linux/docker-ce/centos/ |
优雅地删除节点
删除 master 节点时注意可能需要手动修改 kubeadm-config 中的配置,同时手动修改 /etc/kubernetes/manifests/etcd.yaml 文件移除相关 IP。
1 | kubectl get nodes |
重启容器而非删除
删除容器后会重新进行调度,如果希望在同一个宿主机上重新拉起容器可以执行如下命令:
1 | # 在容器中执行如下命令,会使容器重新创建,但不会重新调度 |
但需要注意的是,上述命令会造成容器重建,所以在容器中进行的非持久修改均会丢失,若想保留临时修改,可先找到容器所在宿主机,然后登录到宿主机上执行 docker restart
重启会保留临时修改,往往用于调试场景。
ServiceAccountTokenVolumeProjection 生成有时效的 Token
参考:https://developer.aliyun.com/article/742572,https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-token-volume-projection,https://www.alibabacloud.com/help/zh/doc-detail/160384.htm
kube-apiserver
1 | --service-account-issuer=kubernetes.default.svc \ |
kube-controller-manager
1 | --controllers=*,bootstrapsigner,tokencleaner,root-ca-cert-publisher \ |
示例
1 | apiVersion: v1 |
kube-controller-manager 10252 port in use
在一定的概率下启动 kube-controller 会出现所需端口已被 kube-apiserver 占用的情况,这是因为 kube-apiserver 向内核申请一个随机端口用于和 etcd 通信,而恰好该端口是稍后 kube-controller-manger 所需的,由于多次出现这种巧合情况,所以对随机算法仍存疑?临时解决方法是调整随机端口范围,避开 10252 端口:
1 | net.ipv4.ip_local_port_range="12000 65535" |
kubelet 启动时持续报错 node not found
一般在经过几次报错后等节点注册成功就会正常,但是有些时候会出现持续报错,此时需要注意的是在 node not found 之前出现的错误,一般解决了这些前置错误就可以了。
编译带 debug 信息的 kubernetes 组件
修改 hack/lib/golang.sh
文件,将 goldflags="${GOLDFLAGS:-} -s -w $(kube::version::ldflags)"
修改为 goldflags="${GOLDFLAGS:-} $(kube::version::ldflags)"
。
1 | // 执行以下命令编译所需二进制程序: |
subpath 挂载 configmap 文件不能自动更新的问题
参考:https://github.com/kubernetes/kubernetes/issues/50345#issuecomment-391888999,不使用 subpath,另建一个目录专门挂载 configmap,从而不会覆盖原目录及其文件,在原目录建一个符号链接指向 confgimap 挂载路径,从而能够利用到自动更新机制。
OOM 时 PreStop 钩子无法发挥作用
当 Pod 内存使用超出 Limit 时,会被内核 oom_killer 杀死,此时由于不是通过 apiserver 发出的删除 pod 调用也不是 Pod 自身的主动终止,所以 PreStop 并不会被触发,为了能够在内存使用超限被杀死前触发 PreStop,一种 walkaround 是通过一个监测内存使用量的程序在内存即将超限(例如 95% )之前实施自杀,从而能够触发 PreStop ,可参考 :https://github.com/16Bitt/kubemem。
在容器内修改系统参数
大多数 namespace 级别的系统参数是安全的,可通过以下方式修改:
1 | apiVersion: apps/v1 |
对于非安全的 namespace 级别的参数需在 kubelet 启动参数中启用后才能进一步设置,kubelet --allowed-unsafe-sysctls 'kernel.msg*,net.core.somaxconn'
。
对于非安全的且为非 namespace 级别的内核参数,只能在宿主机上修改或者给容器添加特权后进入容器修改:
1 | apiVersion: apps/v1 |
Pod SecurityContext 和 Container SecurityContext
DaemonSet 的调度
DaemonSet 相关的 Pod 并不由 kube-scheduler 进行调度,而是由 kube-controller 中的 DaemonSet controller 进行创建和调度,一般的 Pod 总是创建之后先进入 Pending 状态,而 DaemonSet 相关的 Pod 并没有 Pending 状态,Pod 优先级和抢占由 kube-scheduler 去执行,DaemonSet controller 并不会考虑这些,当然也可以通过一些设置(待补充)让调度工作由 kube-scheduler 去完成。DaemonSet controller 会自动为相关 Pod 添加一系列 toleration(包括对网络分区的容忍,对一些节点不可调度状态的容忍等),会造成 cordon 操作无法对 DaemonSet Pod 生效。参考:https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/#taints-and-tolerations
Pod 终止信息
可以在 Pod 意外终止时,向 /dev/termination-log 文件中写入终止原因,方便 Kubernetes 获取信息并填入 Pod 状态字段中。通过以下方式可获取终止原因:
1 | kubectl get pod termination-demo -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}" |
另一方面可以通过 Pod.Spec.Containers[0].terminationMessagePath 自定义文件路径(默认是 /dev/termination-log ),也可以将 Pod.Spec.Containers[0].terminationMessagePolicy 设置为 FallbackToLogsOnError 告诉 Kubernetes 在指定文件内容为空且容器错误退出时,从容器日志中获取最后一段日志信息作为终止信息。参考:https://kubernetes.io/docs/tasks/debug-application-cluster/determine-reason-pod-failure/
Kubernetes log 等级
一般调试开到 5 级即可,参考:https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md。可通过 HTTP 接口热更新日志级别:
1 | # 调整日志级别到3 |
coredns
coredns 支持多种数据来源插件,对于 Kubernetes 的支持是通过 watch Service/Pod/Endpoints/Namespaces 资源动态增删解析记录实现的。
coredns 实现泛域名解析
让 Pod 在节点上均匀分布
在默认的调度策略下,优先考虑到的是资源使用比例的均衡,所以同一个 Deployment 所属的多个 Pod 副本可能集中分布在个别节点上,为了使 Pod 能够在拓扑结构上均匀分布到各个节点上,有两个策略可以考虑:
- 当 Pod 副本数少于节点数量时,可为 Pod 添加 Pod 之间的反亲和性避免同类 Pod 调度到同一个节点上;
- 当 Pod 副本数比节点数量多时,反亲和性可能导致节点无处调度,或者仍然出现多个 Pod 调度到同一节点,一种更为通用的做法是使用 1.16 版本开始引入的 PodTopologySpreadConstraints,可以为 Pod 设置如下属性:
1 | apiVersion: apps/v1 |
升级 Kubernetes 组件和 etcd
参考:https://platform9.com/blog/kubernetes-upgrade-the-definitive-guide-to-do-it-yourself/
查看 Kubernetes 每个版本的发布日志
为系统关键组件设置高优先级
对于部署于集群中的关键组件如 CoreDNS,可通过为 Pod 设置 priorityClassName: system-cluster-critical,来提高优先级,降低集群资源不足时被驱逐后持续 Pending 的概率,system-node-critical 优先级最高,高于 system-cluster-critical。
kube-proxy 的 nftables 实现
https://github.com/zevenet/nftlb,https://github.com/sbezverk/nfproxy,https://github.com/zevenet/kube-nftlb
Service Topology
用于按照节点物理拓扑分发 ClusterIP 或 NodePort 类型的 Service 流量到不同的 Endpoint 去,例如:可以指定集群内 client 端的请求优先分发到同一宿主机或同一机房的 server 端 Pod 去:
1 | # 本例中优先将流量分发至同一宿主机,其次是同一机房,然后是同一地域,最后回退到默认策略 |
Node Conditions
节点 NetworkUnavailable 是否为 True 是通过检查节点上有没有配置好 Pod 网段的路由确定的。节点 Ready Condition 值为 False 说明出现了磁盘、内存或网络等问题, Ready Condition 值为 Unknown 是因为 kubelet 超过 node-monitor-grace-period (默认 40s)没有上报节点状态信息。当 Ready Condition 保持 False 或者 Unknown 超过 pod-eviction-timeout (默认 5 分钟)则 Node controller 将该节点上的 Pod 设置为待删除,若此时节点不可达,API server 无法与 kubelet 通信,则 Pod 将维持 Terminating 或 Unknown 状态直到节点被管理员手动从集群中删除或者节点重新可达。参考:https://kubernetes.io/docs/concepts/architecture/nodes/#condition。
多租户的思考
从 Kubernetes 网络模型的角度来看,Kubernetes 至多实现逻辑上的多租户隔离。多租户的第一步,需要接入用户管理与认证中心,可通过 OpenID 的方式接入;通过 RBAC 控制用户的操作权限,限定用户可以操作的命名空间和资源类型;通过 NetworkPolicy 控制 Pod 之间的网络通信;通过 ResourceQuota 限制 CPU 之类资源的用量和资源对象的数量,从而保证资源使用的公平性;通过 PodSecurityPolicy 限制安全敏感的 Pod 相关字段的设置,如命名空间、系统调用、特权等级;通过 Pod 之间的反亲和性避免不同用户的 Pod 调度到同一节点;通过亲和性或者污点与容忍将特定用户的 Pod 调度到特定节点;引入分层的命名空间实现权限在父子命名空间之间的继承;使用 firecracker 之类的轻量级虚拟机实现 runtime 提升隔离性;进一步可引入 Open Policy Agent 进行应用层的权限验证。
删除命名空间卡在 Terminating
首先要检查命名空间下所有资源删除成功,接下来有两种处理方式:一种是强制删除命名空间,通过如下命令移除所有 finalizer :
1 | for ns in $(kubectl get ns --field-selector status.phase=Terminating -o jsonpath='{.items[*].metadata.name}'); do kubectl get ns $ns -ojson | jq '.spec.finalizers = []' | kubectl replace --raw "/api/v1/namespaces/$ns/finalize" -f -; done |
另一种是查看命名空间 Status 中的 Conditions 信息,找到导致命名空间删除失败的具体原因,进而解决问题后自动删除。
Containerd 导出镜像
1 | crictl images | grep -v IMAGE | grep -v ucloud | awk '{print $1,$2}' | while read image tag; do |
Pod 创建过程简析
使用 kubectl apply 命令时,kubectl 首先从服务端拉取完整的 Kubernetes OpenAPI 定义,然后尝试查询待创建的资源是否已存在,未存在则执行 Post 创建,已存在则与本地文件比较是否需要更新,需要更新则执行 Patch 操作;kube-scheduler watch 到 Pod 创建,则执行调度过程将其调度到某一节点上;kubelet watch 到有 Pod 调度过来,则执行创建过程拉起 Pod。
Liveness, Readiness and Startup Probes
readinessProbe 用来确定服务是否可以接受用户请求,endpoint controller 据此增减 pod ip;livenessProbe 用来确定 Pod 是否存活,kubelet 据此决定是否重启 Pod;readinessProbe 与 livenessProbe 可同时使用,均为持续性检测,可设置检测周期以及失败和成功次数的阈值;startupProbe 用于启动时间较长的 Pod,仅在 Pod 启动时检测,并且启用时 readinessProbe 与 livenessProbe 均被禁用。参考:https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/。
Pod 的删除流程
执行 kubectl delete pod , kubectl 向 api server 发起 Delete 请求;api-server 更新 Pod 信息设置 deletionTimestamp 和 deletionGracePeriodSeconds,Phase 可能仍然是 Running ,不发生变化;kubelet watch 到 Pod 变化,然后开始执行 graceful 删除过程;controller manager watch 到 Pod 变化,从 endpoint 中删除 pod,触发 kube-proxy 更新规则;最后,kubelet 触发 api-server 删除 Pod 对象,这样一个同名的 Pod 可以安全地重建。强制删除会导致 api-server 不等待 kubelet 确认删除 Pod 而直接删除对象,此时允许立即新建一个同名的 Pod,对于 StatefulSet 的应用来说是危险的。
Pod 与 Container 状态
Pod 的 Phase 字段标识 Pod 状态,kubectl get pod 展示的 Status 列并不一定与 Phase 字段一致,而是由 api-server 通过一系列规则计算得到并返回给 kubectl 的,参考代码 printPod,例如当 Pod 的 DeletionTimestamp 字段不为空且节点可达时计算得到的 Status 为 Terminating ;Pod 的 Phase 参考 https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase。
日志收集
日志可大致分为应用日志、K8S 组件日志、Linux 系统日志,另外还有 K8S Events 、APIServer 审计日志也有分析价值,一般可使用 Filebeat 以 DaemonSet 的形式部署到各个节点收集日志,再推送到 Logstash 进行过滤聚合后,推送到 Elasticsearch 进行存储,最后使用 Kibana 查看日志;也可以使用更轻量的 Promtail、Loki、Grafana 的组合。
已用内存的计算
Kubelet 获取的已用内存的值来自于 cgroup memory.usage_in_bytes - memory.stat.total_inactive_file
,total_inactive_file 被包含在 cache 中,实际上 total_active_file 也是包含在 cache 中,在 Linux 内存管理中,一个文件被读或写两次就会被放入 active_file_list,active_file 也可以被回收从而释放内存。相关的讨论参见:https://github.com/kubernetes/kubernetes/issues/43916,https://cloud.tencent.com/developer/article/1637682,Memory_working_set vs Memory_rss in Kubernetes, which one you should monitor?,https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/#active-file-memory-is-not-considered-as-available-memory。
获取 kubelet profile
其它组件的调试信息参考:kubernetes 关键组件 debug。
1 | curl -k --key /etc/kubernetes/ssl/kubelet.key --cert /etc/kubernetes/ssl/kubelet.crt https://NODE_IP:10250/debug/pprof/heap >> heap.info |
Deployment 中使用 PVC
一般来讲 Deployment 应当用来部署无状态应用,需要挂载 PVC 时最好使用 StatefulSet。如果 Deployment 使用了 ReadWriteOnce 的 PVC (块存储),在滚动更新时会因为需要先拉起新的 Pod 再终止旧 Pod 造成同时挂载该 PVC 的情况,这是不允许,所以会一直卡在这个状态。如果想要这样使用,可以把更新策略改成 Recreate ,这样会先删除旧 Pod 再建新 Pod,这必然导致业务中断。另一种方案是使用 ReadWriteMany 的 PVC(文件或对象存储),可以允许多 Pod 同时挂载。
让 Pod 中的容器按顺序启动
一种方案是使用 PostStart 脚本去调用 Container 的健康检查接口,直到容器运行正常后终止脚本,其能够工作的前提是:假如容器的 PostStart
hook 没有正确的返回,kubelet 便不会去创建下一个容器。这种方式是有些 hack 的,而且也无法保证一直能够使用,这不是 kubernetes 保证不会变更的方式。参考:https://mp.weixin.qq.com/s/VulB3tiXTRAjYsuWxgU1Zg。
通过 patch 修改 service 的 status 字段
1 | # cat /tmp/json |
kubectl 部署时默认命名空间的设置
Pod 中执行 kubectl apply 时如果未指定命名空间,并且待部署的资源中也没有明确指定命名空间,则会尝试从几个地方获取命名空间信息,会先尝试从环境变量 POD_NAMESPACE
中读取,读不到则是尝试从当前 context 中获取,如果找不到则继续尝试从 /var/run/secrets/kubernetes.io/serviceaccount/namespace
中获取,参考 https://kubernetes.io/docs/reference/kubectl/overview/#in-cluster-authentication-and-namespace-overrides。
可通过以下命令设置 context 中的命名空间。
1 | kubectl config set-context --current --namespace=default |
在 Pod 中屏蔽 serviceaccount 自动挂载
一种是设置 Pod 的 automountServiceAccountToken 参数,禁止当前 Pod 自动挂载;一种是设置 ServiceAccount 的 automountServiceAccountToken 参数,默认所有 Pod 不自动挂载;一种是 Pod 挂载后再通过自定义挂载覆盖掉自动挂载的目录 /var/run/secrets/kubernetes.io/serviceaccount
。
port-forward 转发 Pod 端口到本地
1 | kubectl port-forward --address 0.0.0.0 pod/mypod 8888:5000 |
十二因素应用
- 十二因素的提出早于 Kubernetes 的大规模使用,但是一些因素和基于 Kubernetes 的服务开发部署有着很好的吻合。可参考: https://skyao.io/learning-cloudnative/factor/ ,https://blog.csdn.net/zeb_perfect/article/details/52536411, https://12factor.net/
- 关于基准代码的理解:每个应用应该使用单独的代码仓库,如果多个应用有需要共享的基准代码,则应当将这部分共享代码组织为一个单独的代码仓库。
Factor 描述 Codebase 基准代码 One codebase tracked in revision control, many deploys 一份基准代码,多份部署 Dependencies 依赖 Explicitly declare and isolate dependencies 显式声明依赖关系 Config 配置 Store config in the environment 在环境中存储配置 Backing services 后端服务 Treat backing services as attached resources 把后端服务当作附加资源 Build, release, run 构建,发布,运行 Strictly separate build and run stages 严格分离构建和运行 Processes 进程 Execute the app as one or more stateless processes 以一个或多个无状态进程运行应用 Port binding 端口绑定 Export services via port binding 通过端口绑定提供服务 Concurrency 并发 Scale out via the process model 通过进程模型进行扩展 Disposability 易处理 Maximize robustness with fast startup and graceful shutdown 快速启动和优雅终止可最大化健壮性 Dev/prod parity 开发环境与线上环境等价 Keep development, staging, and production as similar as possible 尽可能的保持开发,预发布,线上环境相同 Logs 日志 Treat logs as event streams 把日志当作事件流 Admin processes 管理进程 Run admin/management tasks as one-off processes 后台管理任务当作一次性进程运行
书籍
Kubernetes Patterns Reusable Elements for Designing Cloud-Native Applications.pdf