虽然 Docker 已经很强大了,但是在实际使用上还是有诸多不便,比如集群管理、资源调度、文件管理等等。那么在这样一个百花齐放的容器时代涌现出了很多解决方案,比如 Mesos、Swarm、kubernetes 等等,其中谷歌开源的 Kubernetes 是作为老大哥的存在。
kubernetes 已经成为容器编排领域的王者,它是基于容器的集群编排引擎,具备扩展集群、滚动升级回滚、弹性伸缩、自动治愈、服务发现等多种特性能力。
kubernetes 介绍Kubernetes 解决的核心问题Kubernetes 的出现不仅主宰了容器编排的市场,更改变了过去的运维方式,不仅将开发与运维之间边界变得更加模糊,而且让 DevOps 这一角色变得更加清晰,每一个软件工程师都可以通过 Kubernetes 来定义服务之间的拓扑关系、线上的节点个数、资源使用量并且能够快速实现水平扩容、蓝绿部署等在过去复杂的运维操作。
知识图谱主要介绍学习一些什么知识
软件架构传统的客户端服务端架构
Kubernetes 遵循非常传统的客户端/服务端的架构模式,客户端可以通过 RESTful 接口或者直接使用 kubectl 与 Kubernetes 集群进行通信,这两者在实际上并没有太多的区别,后者也只是对 Kubernetes 提供的 RESTful API 进行封装并提供出来。每一个 Kubernetes 集群都是由一组 Master 节点和一系列的 Worker 节点组成,其中 Master 节点主要负责存储集群的状态并为 Kubernetes 对象分配和调度资源。
作为管理集群状态的 Master 节点,它主要负责接收客户端的请求,安排容器的执行并且运行控制循环,将集群的状态向目标状态进行迁移。Master 节点内部由下面三个组件构成:
API Server: 负责处理来自用户的请求,其主要作用就是对外提供 RESTful 的接口,包括用于查看集群状态的读请求以及改变集群状态的写请求,也是唯一一个与 etcd 集群通信的组件。
etcd: 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。
Scheduler: 主节点上的组件,该组件监视那些新创建的未指定运行节点的 pod,并选择节点让 Pod 在上面运行。调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。
controller-manager: 在主节点上运行控制器的组件,从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。这些控制器包括:节点控制器(负责在节点出现故障时进行通知和响应)、副本控制器(负责为系统中的每个副本控制器对象维护正确数量的 Pod)、端点控制器(填充端点 Endpoints 对象,即加入 Service 与 Pod))、服务帐户和令牌控制器(为新的命名空间创建默认帐户和 API 访问令牌)。
其他的 Worker 节点实现就相对比较简单了,它主要由 kubelet 和 kube-proxy 两部分组成。
kubelet: 是工作节点执行操作的 agent,负责具体的容器生命周期管理,根据从数据库中获取的信息来管理容器,并上报 pod 运行状态等。
kube-proxy: 是一个简单的网络访问代理,同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上同一类标签的 Pod。kube-proxy 实质就是通过操作防火墙规则(iptables或者ipvs)来实现 Pod 的映射。
Container Runtime: 容器运行环境是负责运行容器的软件,Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI(容器运行环境接口)。
组件说明主要介绍关于 K8s 的一些基本概念
主要由以下几个核心组件组成:
除了核心组件,还有一些推荐的插件:
以上内容参考链接: www.escapelife.site/posts/2c421…
安装安装v1.16.0版本,竟然成功了。记录在此,避免后来者踩坑。
本篇文章,安装大步骤如下:
详细安装步骤参考:CentOS 搭建 K8S,一次性成功,收藏了! 集群安装教程请参考:全网最新、最详细基于V1.20版本,无坑部署最小化 K8S 集群教程
Pod 实现原理Pod 就是最小并且最简单的 Kubernetes 对象
Pod、Service、Volume 和 Namespace 是 Kubernetes 集群中四大基本对象,它们能够表示系统中部署的应用、工作负载、网络和磁盘资源,共同定义了集群的状态。Kubernetes 中很多其他的资源其实只对这些基本的对象进行了组合。
详细介绍请参考:Kubernetes 之 Pod 实现原理
Harbor 仓库Kuternetes 企业级 Docker 私有仓库 Harbor 工具。 Harbor 的每个组件都是以 Docker 容器的形式构建的,使用 Docker Compose 来对它进行部署。用于部署 Harbor 的 Docker Compose 模板位于 /Deployer/docker-compose.yml 中,其由 5 个容器组成,这几个容器通过 Docker link 的形式连接在一起,在容器之间通过容器名字互相访问。对终端用户而言,只需要暴露 Proxy(即Nginx) 的服务端口即可。
详细介绍与搭建步骤请参考:企业级环境中基于 Harbor 搭建
YAML 语法YAML 是一种非常简洁/强大/专门用来写配置文件的语言!
YAML 全称是 ”YAML Ain’t a Markup Language” 的递归缩写,该语言的设计参考了 JSON / XML 和 SDL 等语言,强调以数据为中心,简洁易读,编写简单。
YAML 语法特性学过编程的人理解起来应该非常容易
语法特点推荐给大家一篇文章:Kubernetes 之 YAML 语法,这篇文章介绍的非常详细,有很多例子说明。
资源清单K8S 中所有的内容都抽象为了资源,资源实例化之后就叫做对象。
在 Kubernetes 系统中,Kubernetes 对象是持久化的实体,Kubernetes 使用这些实体去表示整个集群的状态。特别地,它们描述了如下信息:
Kubernetes 对象是 “目标性记录” —— 一旦创建对象,Kubernetes 系统将持续工作以确保对象存在。通过创建对象,本质上是在告知 Kubernetes 系统,所需要的集群工作负载看起来是什么样子的,这就是 Kubernetes 集群的期望状态。
Kubernetes 之资源清单详细介绍看这里
资源控制器Kubernetes 资源控制器配置文件的编写是学习 K8S 的重中之重!
资源配额控制器确保了指定的资源对象始终不会超过配置的资源,能够有效的降低整个系统宕机的机率,增强系统的鲁棒性,对整个集群的稳定性有非常重要的作用。
Kubernetes 资源控制器使用指南手册
服务发现Kubernetes 中为了实现服务实例间的负载均衡和不同服务间的服务发现,创造了 Service 对象,同时又为从集群外部访问集群创建了 Ingress 对象。
Kubernetes 之服务发现
Ingress 服务我们都知道传统的 svc 只支持四层上面的代码,而对于七层上的代码而无能为力。比如:我们使用 K8S 集群对外提供 HTTPS 的服务,为了方便和便捷,我们需要在对外的 Nginx 服务上面配置 SSL 加密,但是将请求发送给后端服务的时候,进行证书卸载的操作,后续都是用 HTTP 的协议进行处理。而面对此问题,K8S 中给出了使用 Ingress (K8S在1.11版本中推出了)来进行处理。
更多详细内容请参阅:Kubernetes 之 Ingress 服务,介绍关于 Ingress 服务的安装方式,配置关于 Ingress 服务的 HTTP 代理访问,介绍 Ingress 服务的 BasicAuth 认证方式,介绍 Ingress 的进行规则重写的方式。
数据存储在之前的文章中,我们已经知道了很多 K8S 中的组件了,包括资源控制器等。在资源控制器中,我们说到了 StatefulSet 这个控制器组件,其专门为了有状态服务而生的,而对应的存储要存放到哪里呢?
介绍 K8S 中常见的存储机制可以让我们所使用的:Kubernetes 之数据存储
集群调度有这样一个需求,就是集群中多台服务的配置是不一致的。这就导致资源分配并不是均匀的,比如我们需要有些服务节点用来运行计算密集型的服务,而有些服务节点来运行需要大量内存的服务。而在 k8s 中当然也配置了相关服务来处理上述的问题,那就是 Scheduler。
Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 Pod 分配到集群的节点上。听起来非常简单,但有很多要考虑的问题:
Scheduler 是作为单独的程序运行的,启动之后会一直坚挺 API Server,获取 PodSpec.NodeName 为空的 Pod,对每个 Pod 都会创建一个 binding,表明该 Pod 应该放到哪个节点上。
详细的介绍请参考:Kubernetes 之集群调度
kubectl 使用指南kubectl 是 Kubernetes 自带的客户端,可以用它来直接操作 Kubernetes 集群。
日常在使用 Kubernetes 的过程中,kubectl 工具可能是最常用的工具了,所以当我们花费大量的时间去研究和学习 Kuernetes 的时候,那么我们就非常有必要去了解下如何高效的使用它了。
从用户角度来说,kubectl 就是控制 Kubernetes 的驾驶舱,它允许你执行所有可能的 Kubernetes 操作;从技术角度来看,kubectl 就是 Kubernetes API 的一个客户端而已。
Kubernetes API 是一个 HTTP REST API 服务,该 API 服务才是 Kubernetes 的真正用到的用户接口,所以 Kubernetes 通过该 API 进行实际的控制。这也就意味着每个 Kubernetes 的操作都会通过 API 端点暴露出去,当然也就可以通过对这些 API 端口进行 HTTP 请求来执行相应的操作。所以,kubectl 最主要的工作就是执行 Kubernetes API 的 HTTP 请求。
工具使用参数get #显示一个或多个资源
describe #显示资源详情
create #从文件或标准输入创建资源
update #从文件或标准输入更新资源
delete #通过文件名、标准输入、资源名或者 label 删除资源
log #输出 pod 中一个容器的日志
rolling-update #对指定的 RC 执行滚动升级
exec #在容器内部执行命令
port-forward #将本地端口转发到 Pod
proxy #为 Kubernetes API server 启动代理服务器
run #在集群中使用指定镜像启动容器
expose #将 SVC 或 pod 暴露为新的 kubernetes service
label #更新资源的 label
config #修改 kubernetes 配置文件
cluster-info #显示集群信息
api-versions #以”组/版本”的格式输出服务端支持的 API 版本
version #输出服务端和客户端的版本信息
help #显示各个命令的帮助信息
ingress-nginx #管理 ingress 服务的插件(官方安装和使用方式)
复制代码
使用相关配置
# Kubectl自动补全
$ source <(kubectl completion zsh)
$ source <(kubectl completion bash)
# 显示合并后的 kubeconfig 配置
$ kubectl config view
# 获取pod和svc的文档
$ kubectl explain pods,svc
复制代码
创建资源对象分步骤创建
# yaml
kubectl create -f xxx-rc.yaml
kubectl create -f xxx-service.yaml
# json
kubectl create -f ./pod.json
cat pod.json | kubectl create -f -
# yaml2json
kubectl create -f docker-registry.yaml --edit -o json
复制代码
一次性创建
kubectl create -f xxx-service.yaml -f xxx-rc.yaml
复制代码
根据目录下所有的 yaml 文件定义内容进行创建
kubectl create -f <目录>
复制代码
使用 url 来创建资源
kubectl create -f https://git.io/vPieo
复制代码
查看资源对象查看所有 Node 或 Namespace 对象
kubectl get nodes
kubectl get namespace
复制代码
查看所有 Pod 对象
# 查看子命令帮助信息
kubectl get --help
# 列出默认namespace中的所有pod
kubectl get pods
# 列出指定namespace中的所有pod
kubectl get pods --namespace=test
# 列出所有namespace中的所有pod
kubectl get pods --all-namespaces
# 列出所有pod并显示详细信息
kubectl get pods -o wide
kubectl get replicationcontroller web
kubectl get -k dir/
kubectl get -f pod.yaml -o json
kubectl get rc/web service/frontend pods/web-pod-13je7
kubectl get pods/app-prod-78998bf7c6-ttp9g --namespace=test -o wide
kubectl get -o template pod/web-pod-13je7 --template={{.status.phase}}
# 列出该namespace中的所有pod包括未初始化的
kubectl get pods,rc,services --include-uninitialized
复制代码
查看所有 RC 对象
kubectl get rc
复制代码
查看所有 Deployment 对象
# 查看全部deployment
kubectl get deployment
# 列出指定deployment
kubectl get deployment my-app
复制代码
查看所有 Service 对象
kubectl get svc
kubectl get service
复制代码
查看不同 Namespace 下的 Pod 对象
kubectl get pods -n default
kubectl get pods --all-namespace
复制代码
查看资源描述显示 Pod 详细信息
kubectl describe pods/nginx
kubectl describe pods my-pod
kubectl describe -f pod.json
复制代码
查看 Node 详细信息
kubectl describe nodes c1
复制代码
查看 RC 关联的 Pod 信息
kubectl describe pods <rc-name>
复制代码
更新修补资源滚动更新
# 滚动更新 pod frontend-v1
kubectl rolling-update frontend-v1 -f frontend-v2.json
# 更新资源名称并更新镜像
kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
# 更新 frontend pod 中的镜像
kubectl rolling-update frontend --image=image:v2
# 退出已存在的进行中的滚动更新
kubectl rolling-update frontend-v1 frontend-v2 --rollback
# 强制替换; 删除后重新创建资源; 服务会中断
kubectl replace --force -f ./pod.json
# 添加标签
kubectl label pods my-pod new-label=awesome
# 添加注解
kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq
复制代码
修补资源
# 部分更新节点
kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}'
# 更新容器镜像;spec.containers[*].name 是必须的,因为这是合并的关键字
kubectl patch pod valid-pod -p \
'{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'
复制代码
Scale 资源
# Scale a replicaset named 'foo' to 3
kubectl scale --replicas=3 rs/foo
# Scale a resource specified in "foo.yaml" to 3
kubectl scale --replicas=3 -f foo.yaml
# If the deployment named mysql's current size is 2, scale mysql to 3
kubectl scale --current-replicas=2 --replicas=3 deployment/mysql
# Scale multiple replication controllers
kubectl scale --replicas=5 rc/foo rc/bar rc/baz
复制代码
删除资源对象基于 xxx.yaml 文件删除 Pod 对象
# yaml文件名字按照你创建时的文件一致
kubectl delete -f xxx.yaml
复制代码
删除包括某个 label 的 pod 对象
kubectl delete pods -l name=<label-name>
复制代码
删除包括某个 label 的 service 对象
kubectl delete services -l name=<label-name>
复制代码
删除包括某个 label 的 pod 和 service 对象
kubectl delete pods,services -l name=<label-name>
复制代码
删除所有 pod/services 对象
kubectl delete pods --all
kubectl delete service --all
kubectl delete deployment --all
复制代码
编辑资源文件
在编辑器中编辑任何 API 资源
# 编辑名为docker-registry的service
kubectl edit svc/docker-registry
复制代码
直接执行命令
在寄主机上,不进入容器直接执行命令
执行 pod 的 date 命令,默认使用 pod 的第一个容器执行kubectl exec mypod -- date
kubectl exec mypod --namespace=test -- date
复制代码
指定 pod 中某个容器执行 date 命令
kubectl exec mypod -c ruby-container -- date
复制代码
进入某个容器
kubectl exec mypod -c ruby-container -it -- bash
复制代码
查看容器日志直接查看日志
# 不实时刷新kubectl logs mypod
kubectl logs mypod --namespace=test
复制代码
查看日志实时刷新
kubectl logs -f mypod -c ruby-container
复制代码
管理工具
Kubernetes正在不断加快在云原生环境的应用,但如何以统一、安全的方式对运行于任何地方的Kubernetes集群进行管理面临着挑战,而有效的管理工具能够大大降低管理的难度。
K9sk9s是基于终端的资源仪表板。它只有一个命令行界面。无论在Kubernetes仪表板Web UI上做什么,都可以在终端使用K9s仪表板工具进行相同的操作。k9s持续关注Kubernetes集群,并提供命令以使用集群上定义的资源。
详细介绍:Kubernetes 集群管理工具 K9S
推荐:轻松管理 Kubernetes 集群的7个工具
生产环境最佳实践使用Kubernetes的一些策略,在安全性、监控、网络、治理、存储、容器生命周期管理和平台选择方面应用最佳实践。下面让我们来看看Kubernetes的一些生产最佳实践。在生产中运行Kubernetes并不容易; 有以下几个方面需要注意。
是否使用存活探针和就绪探针进行健康检查?管理大型分布式系统可能会很复杂,特别是当出现问题时,我们无法及时得到通知。为了确保应用实例正常工作,设置Kubernetes健康检查至关重要。
通过创建自定义运行健康检查,可以有效避免分布式系统中僵尸服务运行,具体可以根据环境和需要对其进行调整。
就绪探针的目的是让Kubernetes知道该应用是否已经准备好为流量服务。Kubernetes将始终确保准备就绪探针通过之后开始分配服务,将流量发送到Pod。
Liveness-存活探针你怎么知道你的应用程序是活的还是死的?存活探针可以让你做到这一点。如果你的应用死了,Kubernetes会移除旧的Pod并用新Pod替换它。
Resource Management-资源管理为单个容器指定资源请求和限制是一个很好的实践。另一个好的实践是将Kubernetes环境划分为不同团队、部门、应用程序和客户机的独立名称空间。
Kubernetes资源使用情况Kubernetes资源使用指的是容器/pod在生产中所使用的资源数量。
因此,密切关注pods的资源使用情况是非常重要的。一个明显的原因是成本,因为越高的资源利用证明越少的资源浪费。
Resource utilization资源利用率Ops团队通常希望优化和最大化pods消耗的资源百分比。资源使用情况是Kubernetes环境实际优化程度的指标之一。
您可以认为优化后的Kubernetes环境中运行的容器的平均CPU等资源利用率是最优的。
启用RBACRBAC代表基于角色的访问控制。它是一种用于限制系统/网络上的用户和应用程序的访问和准入的方法。!
他们从Kubernetes 1.8版本引入了RBAC。使用rbac.authorization.k8s RBAC用于创建授权策略。
在Kubernetes中,RBAC用于授权,使用RBAC,您将能够授予用户、帐户、添加/删除权限、设置规则等权限。因此,它基本上为Kubernetes集群添加了额外的安全层。RBAC限制谁可以访问您的生产环境和集群。
集群置备和负载均衡生产级Kubernetes基础设施通常需要考虑某些关键方面,例如高可用性、多主机、多etcd Kubernetes集群等。此类集群的配置通常涉及到Terraform或Ansible等工具。
一旦集群都设置好了,并且为运行应用程序创建了pods,这些pods就配备了负载平衡器;这些负载均衡器将流量路由到服务。开源的Kubernetes项目并不是默认的负载平衡器;因此,它需要与NGINX Ingress controller与HAProxy或ELB等工具集成,或任何其他工具,扩大Kubernetes的Ingress插件,以提供负载均衡能力。
给Kubernetes对象添加标签标签就像附加到对象上的键/值对,比如pods。标签是用来标识对象的属性的,这些属性对用户来说是重要的和有意义的。
在生产中使用Kubernetes时,不能忽视的一个重要问题是标签;标签允许批量查询和操作Kubernetes对象。标签的特殊之处在于,它们还可以用于识别Kubernetes对象并将其组织成组。这样做的最佳用例之一是根据pod所属的应用程序对它们进行分组。在这里,团队可以构建并拥有任意数量的标签约定。
配置网络策略使用Kubernetes时,设置网络策略至关重要。网络策略只不过是一个对象,它使你能够明确地声明和决定哪些流量是允许的,哪些是不允许的。这样,Kubernetes将能够阻止所有其他不想要的和不符合规则的流量。在我们的集群中定义和限制网络流量是强烈推荐的基本且必要的安全措施之一。
Kubernetes中的每个网络策略都定义了一个如上所述的授权连接列表。无论何时创建任何网络策略,它所引用的所有pod都有资格建立或接受列出的连接。简单地说,网络策略基本上就是授权和允许连接的白名单——一个连接,无论它是到还是从pod,只有在应用于pod的至少一个网络策略允许的情况下才被允许。
集群监控和日志记录在使用Kubernetes时,监控部署是至关重要的。确保配置、性能和流量保持安全更是重要。如果不进行日志记录和监控,就不可能诊断出发生的问题。为了确保合规性,监视和日志记录变得非常重要。在进行监视时,有必要在体系结构的每一层上设置日志记录功能。生成的日志将帮助我们启用安全工具、审计功能和分析性能。
从无状态应用程序开始运行无状态应用要比运行有状态应用简单得多,但随着Kubernetes运营商的不断增长,这种想法正在改变。对于刚接触Kubernetes的团队来说,建议首先使用无状态应用程序。
建议使用无状态后端,这样开发团队就可以确保不存在长时间运行的连接,从而增加了扩展的难度。使用无状态,开发人员还可以更有效地、零停机部署应用程序。人们普遍认为,无状态应用程序可以方便地根据业务需要进行迁移和扩展。
边启动自动扩缩容Kubernetes有三种用于部署的自动伸缩功能:水平pod自动伸缩(HPA)、垂直pod自动伸缩(VPA)和集群自动伸缩。
水平pod autoscaler根据感知到的CPU利用率自动扩展deployment、replicationcontroller, replicaset, statefulset的数量。
Vertical pod autoscaling为CPU和内存请求和限制推荐合适的值,它可以自动更新这些值。
Cluster Autoscaler扩展和缩小工作节点池的大小。它根据当前的利用率调整Kubernetes集群的大小。
控制镜像拉取来源控制在集群中运行所有容器的镜像源。如果您允许您的Pod从公共资源中拉取镜像,您就不知道其中真正运行的是什么。
如果从受信任的注册表中提取它们,则可以在注册表上应用策略以提取安全和经过认证的镜像。
持续学习不断评估应用程序的状态和设置,以学习和改进。例如,回顾容器的历史内存使用情况可以得出这样的结论:我们可以分配更少的内存,在长期内节省成本。
保护重要服务使用Pod优先级,您可以决定设置不同服务运行的重要性。例如,为了更好的稳定性,你需要确保RabbitMQ pod比你的应用pod更重要。或者你的入口控制器pods比数据处理pods更重要,以保持服务对用户可用。
零停机时间通过在HA中运行所有服务,支持集群和服务的零停机升级。这也将保证您的客户获得更高的可用性。
使用pod反亲和性来确保在不同的节点上调度一个pod的多个副本,从而通过计划中的和计划外的集群节点停机来确保服务可用性。
使用pod Disruptions策略,不惜一切代价确保您有最低的Pod副本数量!
计划失败硬件最终会失败,软件最终会运行。--(迈克尔·哈顿)
结论众所周知,Kubernetes实际上已经成为DevOps领域的编排平台标准。Kubernetes从可用性、可伸缩性、安全性、弹性、资源管理和监控的角度来应对生产环境产生的风暴。由于许多公司都在生产中使用Kubernetes,因此必须遵循上面提到的最佳实践,以顺利和可靠地扩展应用程序。
内容来源:my.oschina.net/u/1787735/b…
介绍5 款顶级 Kubernetes 日志监控工具对于新安装的 Kubernetes,经常出现的一个问题是 Service 没有正常工作。如果您已经运行了 Deployment 并创建了一个 Service,但是当您尝试访问它时没有得到响应,希望这份文档(全网最详细的 K8s Service 不能访问排查流程)能帮助您找出问题所在。
Kubernetes 常见问题总结如何删除不一致状态下的 rc,deployment,service在某些情况下,经常发现 kubectl 进程挂起现象,然后在 get 时候发现删了一半,而另外的删除不了
[root@k8s-master ~]# kubectl get -f fluentd-elasticsearch/
NAME DESIRED CURRENT READY AGE
rc/elasticsearch-logging-v1 0 2 2 15h
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/kibana-logging 0 1 1 1 15h
Error from server (NotFound): services "elasticsearch-logging" not found
Error from server (NotFound): daemonsets.extensions "fluentd-es-v1.22" not found
Error from server (NotFound): services "kibana-logging" not found
复制代码
删除这些 deployment,service 或者 rc 命令如下:
kubectl delete deployment kibana-logging -n kube-system --cascade=false
kubectl delete deployment kibana-logging -n kube-system --ignore-not-found
delete rc elasticsearch-logging-v1 -n kube-system --force now --grace-period=0
复制代码
删除不了后如何重置 etcd
rm -rf /var/lib/etcd/*
复制代码
删除后重新 reboot master 结点。
reset etcd 后需要重新设置网络
etcdctl mk /atomic.io/network/config '{ "Network": "192.168.0.0/16" }'
复制代码
启动 apiserver 失败
每次启动都是报如下问题:
start request repeated too quickly for kube-apiserver.service
复制代码
但其实不是启动频率问题,需要查看, /var/log/messages,在我的情况中是因为开启 ServiceAccount 后找不到 ca.crt 等文件,导致启动出错。
May 21 07:56:41 k8s-master kube-apiserver: Flag --port has been deprecated, see --insecure-port instead.
May 21 07:56:41 k8s-master kube-apiserver: F0521 07:56:41.692480 4299 universal_validation.go:104] Validate server run options failed: unable to load client CA file: open /var/run/kubernetes/ca.crt: no such file or directory
May 21 07:56:41 k8s-master systemd: kube-apiserver.service: main process exited, code=exited, status=255/n/a
May 21 07:56:41 k8s-master systemd: Failed to start Kubernetes API Server.
May 21 07:56:41 k8s-master systemd: Unit kube-apiserver.service entered failed state.
May 21 07:56:41 k8s-master systemd: kube-apiserver.service failed.
May 21 07:56:41 k8s-master systemd: kube-apiserver.service holdoff time over, scheduling restart.
May 21 07:56:41 k8s-master systemd: start request repeated too quickly for kube-apiserver.service
May 21 07:56:41 k8s-master systemd: Failed to start Kubernetes API Server.
复制代码
在部署 fluentd 等日志组件的时候,很多问题都是因为需要开启 ServiceAccount 选项需要配置安全导致,所以说到底还是需要配置好 ServiceAccount.
出现 Permission denied 情况在配置 fluentd 时候出现cannot create /var/log/fluentd.log: Permission denied 错误,这是因为没有关掉 SElinux 安全导致。
可以在 /etc/selinux/config 中将 SELINUX=enforcing 设置成 disabled,然后 reboot
基于 ServiceAccount 的配置首先生成各种需要的 keys,k8s-master 需替换成 master 的主机名.
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=k8s-master" -days 10000 -out ca.crt
openssl genrsa -out server.key 2048
echo subjectAltName=IP:10.254.0.1 > extfile.cnf
#ip由下述命令决定
#kubectl get services --all-namespaces |grep 'default'|grep 'kubernetes'|grep '443'|awk '{print $3}'
openssl req -new -key server.key -subj "/CN=k8s-master" -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out server.crt -days 10000
复制代码
如果修改 /etc/kubernetes/apiserver 的配置文件参数的话,通过 systemctl start kube-apiserver 启动失败,出错信息为:
Validate server run options failed: unable to load client CA file: open /root/keys/ca.crt: permission denied
复制代码
但可以通过命令行启动 API Server
/usr/bin/kube-apiserver --logtostderr=true --v=0 --etcd-servers=http://k8s-master:2379 --address=0.0.0.0 --port=8080 --kubelet-port=10250 --allow-privileged=true --service-cluster-ip-range=10.254.0.0/16 --admission-control=ServiceAccount --insecure-bind-address=0.0.0.0 --client-ca-file=/root/keys/ca.crt --tls-cert-file=/root/keys/server.crt --tls-private-key-file=/root/keys/server.key --basic-auth-file=/root/keys/basic_auth.csv --secure-port=443 &>> /var/log/kubernetes/kube-apiserver.log &
复制代码
命令行启动 Controller-manager
/usr/bin/kube-controller-manager --logtostderr=true --v=0 --master=http://k8s-master:8080 --root-ca-file=/root/keys/ca.crt --service-account-private-key-file=/root/keys/server.key & >>/var/log/kubernetes/kube-controller-manage.log
复制代码
ETCD 启动不起来-问题<1>
etcd是kubernetes 集群的zookeeper进程,几乎所有的service都依赖于etcd的启动,比如flanneld,apiserver,docker.....在启动etcd是报错日志如下:
May 24 13:39:09 k8s-master systemd: Stopped Flanneld overlay address etcd agent.
May 24 13:39:28 k8s-master systemd: Starting Etcd Server...
May 24 13:39:28 k8s-master etcd: recognized and used environment variable ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379,http://etcd:4001
May 24 13:39:28 k8s-master etcd: recognized environment variable ETCD_NAME, but unused: shadowed by corresponding flag
May 24 13:39:28 k8s-master etcd: recognized environment variable ETCD_DATA_DIR, but unused: shadowed by corresponding flag
May 24 13:39:28 k8s-master etcd: recognized environment variable ETCD_LISTEN_CLIENT_URLS, but unused: shadowed by corresponding flag
May 24 13:39:28 k8s-master etcd: etcd Version: 3.1.3
May 24 13:39:28 k8s-master etcd: Git SHA: 21fdcc6
May 24 13:39:28 k8s-master etcd: Go Version: go1.7.4
May 24 13:39:28 k8s-master etcd: Go OS/Arch: linux/amd64
May 24 13:39:28 k8s-master etcd: setting maximum number of CPUs to 1, total number of available CPUs is 1
May 24 13:39:28 k8s-master etcd: the server is already initialized as member before, starting as etcd member...
May 24 13:39:28 k8s-master etcd: listening for peers on http://localhost:2380
May 24 13:39:28 k8s-master etcd: listening for client requests on 0.0.0.0:2379
May 24 13:39:28 k8s-master etcd: listening for client requests on 0.0.0.0:4001
May 24 13:39:28 k8s-master etcd: recovered store from snapshot at index 140014
May 24 13:39:28 k8s-master etcd: name = master
May 24 13:39:28 k8s-master etcd: data dir = /var/lib/etcd/default.etcd
May 24 13:39:28 k8s-master etcd: member dir = /var/lib/etcd/default.etcd/member
May 24 13:39:28 k8s-master etcd: heartbeat = 100ms
May 24 13:39:28 k8s-master etcd: election = 1000ms
May 24 13:39:28 k8s-master etcd: snapshot count = 10000
May 24 13:39:28 k8s-master etcd: advertise client URLs = http://etcd:2379,http://etcd:4001
May 24 13:39:28 k8s-master etcd: ignored file 0000000000000001-0000000000012700.wal.broken in wal
May 24 13:39:29 k8s-master etcd: restarting member 8e9e05c52164694d in cluster cdf818194e3a8c32 at commit index 148905
May 24 13:39:29 k8s-master etcd: 8e9e05c52164694d became follower at term 12
May 24 13:39:29 k8s-master etcd: newRaft 8e9e05c52164694d [peers: [8e9e05c52164694d], term: 12, commit: 148905, applied: 140014, lastindex: 148905, lastterm: 12]
May 24 13:39:29 k8s-master etcd: enabled capabilities for version 3.1
May 24 13:39:29 k8s-master etcd: added member 8e9e05c52164694d [http://localhost:2380] to cluster cdf818194e3a8c32 from store
May 24 13:39:29 k8s-master etcd: set the cluster version to 3.1 from store
May 24 13:39:29 k8s-master etcd: starting server... [version: 3.1.3, cluster version: 3.1]
May 24 13:39:29 k8s-master etcd: raft save state and entries error: open /var/lib/etcd/default.etcd/member/wal/0.tmp: is a directory
May 24 13:39:29 k8s-master systemd: etcd.service: main process exited, code=exited, status=1/FAILURE
May 24 13:39:29 k8s-master systemd: Failed to start Etcd Server.
May 24 13:39:29 k8s-master systemd: Unit etcd.service entered failed state.
May 24 13:39:29 k8s-master systemd: etcd.service failed.
May 24 13:39:29 k8s-master systemd: etcd.service holdoff time over, scheduling restart.
复制代码
核心语句:
raft save state and entries error: open /var/lib/etcd/default.etcd/member/wal/0.tmp: is a directory
复制代码
进入相关目录,删除 0.tmp,然后就可以启动啦!
ETCD启动不起来-超时问题<2>问题背景:当前部署了 3 个 etcd 节点,突然有一天 3 台集群全部停电宕机了。重新启动之后发现 K8S 集群是可以正常使用的,但是检查了一遍组件之后,发现有一个节点的 etcd 启动不了。
经过一遍探查,发现时间不准确,通过以下命令 ntpdate ntp.aliyun.com 重新将时间调整正确,重新启动 etcd,发现还是起不来,报错如下:
Mar 05 14:27:15 k8s-node2 etcd[3248]: etcd Version: 3.3.13
Mar 05 14:27:15 k8s-node2 etcd[3248]: Git SHA: 98d3084
Mar 05 14:27:15 k8s-node2 etcd[3248]: Go Version: go1.10.8
Mar 05 14:27:15 k8s-node2 etcd[3248]: Go OS/Arch: linux/amd64
Mar 05 14:27:15 k8s-node2 etcd[3248]: setting maximum number of CPUs to 4, total number of available CPUs is 4
Mar 05 14:27:15 k8s-node2 etcd[3248]: the server is already initialized as member before, starting as etcd member
...
Mar 05 14:27:15 k8s-node2 etcd[3248]: peerTLS: cert = /opt/etcd/ssl/server.pem, key = /opt/etcd/ssl/server-key.pe
m, ca = , trusted-ca = /opt/etcd/ssl/ca.pem, client-cert-auth = false, crl-file =
Mar 05 14:27:15 k8s-node2 etcd[3248]: listening for peers on https://192.168.25.226:2380
Mar 05 14:27:15 k8s-node2 etcd[3248]: The scheme of client url http://127.0.0.1:2379 is HTTP while peer key/cert
files are presented. Ignored key/cert files.
Mar 05 14:27:15 k8s-node2 etcd[3248]: listening for client requests on 127.0.0.1:2379
Mar 05 14:27:15 k8s-node2 etcd[3248]: listening for client requests on 192.168.25.226:2379
Mar 05 14:27:15 k8s-node2 etcd[3248]: member 9c166b8b7cb6ecb8 has already been bootstrapped
Mar 05 14:27:15 k8s-node2 systemd[1]: etcd.service: main process exited, code=exited, status=1/FAILURE
Mar 05 14:27:15 k8s-node2 systemd[1]: Failed to start Etcd Server.
Mar 05 14:27:15 k8s-node2 systemd[1]: Unit etcd.service entered failed state.
Mar 05 14:27:15 k8s-node2 systemd[1]: etcd.service failed.
Mar 05 14:27:15 k8s-node2 systemd[1]: etcd.service failed.
Mar 05 14:27:15 k8s-node2 systemd[1]: etcd.service holdoff time over, scheduling restart.
Mar 05 14:27:15 k8s-node2 systemd[1]: Starting Etcd Server...
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_NAME, but unused: shadowed by correspo
nding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_DATA_DIR, but unused: shadowed by corr
esponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_LISTEN_PEER_URLS, but unused: shadowed
by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_LISTEN_CLIENT_URLS, but unused: shadow
ed by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_INITIAL_ADVERTISE_PEER_URLS, but unuse
d: shadowed by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_ADVERTISE_CLIENT_URLS, but unused: sha
dowed by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_INITIAL_CLUSTER, but unused: shadowed
by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_INITIAL_CLUSTER_TOKEN, but unused: sha
dowed by corresponding flag
Mar 05 14:27:15 k8s-node2 etcd[3258]: recognized environment variable ETCD_INITIAL_CLUSTER_STATE, but unused: sha
dowed by corresponding flag
复制代码
解决方法:
检查日志发现并没有特别明显的错误,根据经验来讲,etcd 节点坏掉一个其实对集群没有大的影响,这时集群已经可以正常使用了,但是这个坏掉的 etcd 节点并没有启动,解决方法如下:
进入 etcd 的数据存储目录进行备份 备份原有数据:
cd /var/lib/etcd/default.etcd/member/
cp * /data/bak/
复制代码
删除这个目录下的所有数据文件
rm -rf /var/lib/etcd/default.etcd/member/*
复制代码
停止另外两台 etcd 节点,因为 etcd 节点启动时需要所有节点一起启动,启动成功后即可使用。
#master 节点
systemctl stop etcd
systemctl restart etcd
#node1 节点
systemctl stop etcd
systemctl restart etcd
#node2 节点
systemctl stop etcd
systemctl restart etcd
复制代码
CentOS下配置主机互信
在每台服务器需要建立主机互信的用户名执行以下命令生成公钥/密钥,默认回车即可
ssh-keygen -t rsa
复制代码
可以看到生成个公钥的文件。
互传公钥,第一次需要输入密码,之后就OK了。
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.199.132 (-p 2222)
复制代码
-p 端口 默认端口不加-p,如果更改过端口,就得加上-p. 可以看到是在.ssh/下生成了个 authorized_keys的文件,记录了能登陆这台服务器的其他服务器的公钥。
测试看是否能登陆:
ssh 192.168.199.132 (-p 2222)
复制代码
CentOS 主机名的修改
hostnamectl set-hostname k8s-master1
复制代码
Virtualbox 实现 CentOS 复制和粘贴功能
如果不安装或者不输出,可以将 update 修改成 install 再运行。
yum install update
yum update kernel
yum update kernel-devel
yum install kernel-headers
yum install gcc
yum install gcc make
复制代码
运行完后
sh VBoxLinuxAdditions.run
复制代码
删除Pod一直处于Terminating状态
可以通过下面命令强制删除
kubectl delete pod NAME --grace-period=0 --force
复制代码
删除namespace一直处于Terminating状态
可以通过以下脚本强制删除
[root@k8s-master1 k8s]# cat delete-ns.sh
#!/bin/bash
set -e
useage(){
echo "useage:"
echo " delns.sh NAMESPACE"
}
if [ $# -lt 1 ];then
useage
exit
fi
NAMESPACE=$1
JSONFILE=${NAMESPACE}.json
kubectl get ns "${NAMESPACE}" -o json > "${JSONFILE}"
vi "${JSONFILE}"
curl -k -H "Content-Type: application/json" -X PUT --data-binary @"${JSONFLE}" \
http://127.0.0.1:8001/api/v1/namespaces/"${NAMESPACE}"/finalize
复制代码
容器包含有效的 CPU/内存 requests 且没有指定 limits 可能会出现什么问题?
下面我们创建一个对应的容器,该容器只有 requests 设定,但是没有 limits 设定,
- name: busybox-cnt02
image: busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello from cnt02; sleep 10;done"]
resources:
requests:
memory: "100Mi"
cpu: "100m"
复制代码
这个容器创建出来会有什么问题呢?
其实对于正常的环境来说没有什么问题,但是对于资源型 pod 来说,如果有的容器没有设定 limit 限制,资源会被其他的 pod 抢占走,可能会造成容器应用失败的情况。可以通过 limitrange 策略来去匹配,让 pod 自动设定,前提是要提前配置好limitrange 规则。
来源:www.cnblogs.com/passzhang
Kubernetes 上对应用程序进行故障排除的 6 个技巧 推荐给大家,日常排错必备。分享一份阿里云内部超全K8s实战手册,免费下载!
面试题一个目标:容器操作;两地三中心;四层服务发现;五种 Pod 共享资源;六个 CNI 常用插件;七层负载均衡;八种隔离维度;九个网络模型原则;十类 IP 地址;百级产品线;千级物理机;万级容器;相如无亿,k8s 有亿:亿级日服务人次。
一个目标:容器操作Kubernetes(k8s)是自动化容器操作的开源平台。这些容器操作包括:部署、调度和节点集群间扩展。
具体功能:下面是 k8s 的架构拓扑图:
两地三中心
两地三中心包括本地生产中心、本地灾备中心、异地灾备中心。
两地三中心要解决的一个重要问题就是数据一致性问题。
k8s 使用 etcd 组件作为一个高可用、强一致性的服务发现存储仓库。用于配置共享和服务发现。
它作为一个受到 Zookeeper 和 doozer 启发而催生的项目。除了拥有他们的所有功能之外,还拥有以下 4 个特点:
先一张图解释一下网络七层协议:
k8s 提供了两种方式进行服务发现:
以上两种方式,一个是基于 TCP,DNS 基于 UDP,它们都是建立在四层协议之上。
五种 Pod 共享资源Pod 是 k8s 最基本的操作单元,包含一个或多个紧密相关的容器。
一个 Pod 可以被一个容器化的环境看作应用层的“逻辑宿主机”;一个 Pod 中的多个容器应用通常是紧密耦合的,Pod 在 Node 上被创建、启动或者销毁;每个 Pod 里运行着一个特殊的被称之为 Volume 挂载卷,因此他们之间通信和数据交换更为高效。在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个 Pod 中。
同一个 Pod 里的容器之间仅需通过 localhost 就能互相通信。
一个 Pod 中的应用容器共享五种资源:
Pod 的生命周期通过 Replication Controller 来管理;通过模板进行定义,然后分配到一个 Node 上运行,在 Pod 所包含容器运行结束后,Pod 结束。
Kubernetes 为 Pod 设计了一套独特的网络配置,包括为每个 Pod 分配一个IP地址,使用 Pod 名作为容器间通信的主机名等。
六个 CNI 常用插件CNI(Container Network Interface)容器网络接口是 Linux 容器网络配置的一组标准和库,用户需要根据这些标准和库来开发自己的容器网络插件。CNI 只专注解决容器网络连接和容器销毁时的资源释放,提供一套框架。所以 CNI 可以支持大量不同的网络模式,并且容易实现。
下面用一张图表示六个 CNI 常用插件:
七层负载均衡提负载均衡就不得不先提服务器之间的通信。
IDC(Internet Data Center)也可称数据中心、机房,用来放置服务器。IDC 网络是服务器间通信的桥梁。
上图里画了很多网络设备,它们都是干啥用的呢?
路由器、交换机、MGW/NAT 都是网络设备,按照性能、内外网划分不同的角色。
先说说各层负载均衡:
这里用一张图来说说四层和七层负载均衡的区别:
上面四层服务发现讲的主要是 k8s 原生的 kube-proxy 方式。k8s 关于服务的暴露主要是通过 NodePort 方式,通过绑定 minion 主机的某个端口,然后进行 Pod 的请求转发和负载均衡,但这种方式有下面的缺陷:
理想的方式是通过一个外部的负载均衡器,绑定固定的端口,比如 80;然后根据域名或者服务名向后面的 Service IP 转发。
Nginx 很好的解决了这个需求,但问题是如果有的新的服务加入,如何去修改并且加载这些 Nginx 配置?
Kubernetes 给出的方案就是 Ingress。这是一个基于七层的方案。
八种隔离维度k8s 集群调度这边需要对上面从上到下、从粗粒度到细粒度的隔离做相应的调度策略。
九个网络模型原则k8s 网络模型要符合四个基础原则、三个网络要求原则、一个架构原则、一个 IP 原则。
每个 Pod 都拥有一个独立的 IP 地址,而且假定所有 Pod 都在一个可以直接连通的、扁平的网络空间中,不管是否运行在同一 Node 上都可以通过 Pod 的 IP 来访问。
k8s 中的 Pod 的 IP 是最小粒度 IP。同一个 Pod 内所有的容器共享一个网络堆栈,该模型称为 IP-per-Pod 模型。
IP-per-Pod 模型从端口分配、域名解析、服务发现、负载均衡、应用配置等角度看,Pod 可以看做是一台独立的虚拟机或物理机。
要符合下面的架构:
由上图架构引申出来 IP 概念从集群外部到集群内部:
十类IP地址
大家都知道 IP 地址分为 ABCDE 类,另外还有五类特殊用途的 IP。
第一类
A 类:1.0.0.0-1226.255.255.255,默认子网掩码/8,即255.0.0.0。
B 类:128.0.0.0-191.255.255.255,默认子网掩码/16,即255.255.0.0。
C 类:192.0.0.0-223.255.255.255,默认子网掩码/24,即255.255.255.0。
D 类:224.0.0.0-239.255.255.255,一般用于组播。
E 类:240.0.0.0-255.255.255.255(其中255.255.255.255为全网广播地址)。E 类地址一般用于研究用途。
复制代码
第二类
0.0.0.0
严格来说,0.0.0.0 已经不是一个真正意义上的 IP 地址了。它表示的是这样一个集合:所有不清楚的主机和目的网络。这里的不清楚是指在本机的路由表里没有特定条目指明如何到达。作为缺省路由。
127.0.0.1 本机地址。
复制代码
第三类
224.0.0.1 组播地址。
如果你的主机开启了IRDP(internet路由发现,使用组播功能),那么你的主机路由表中应该有这样一条路由。
复制代码
第四类
169.254.x.x
使用了 DHCP 功能自动获取了 IP 的主机,DHCP 服务器发生故障,或响应时间太长而超出了一个系统规定的时间,系统会为你分配这样一个 IP,代表网络不能正常运行。
复制代码
第五类
10.xxx、172.16.x.x~172.31.x.x、192.168.x.x 私有地址。
大量用于企业内部。保留这样的地址是为了避免亦或是哪个接入公网时引起地址混乱。
Pod(豌豆荚)篇
3.Pod创建流程图示1;RS 跟 RC 没有本质的不同,只是名字不不同,且RS 支持集合式的 selector
2: 通过 RS 与 Deployment 的关联一起使用
图来自网络(侵删):
Kubernetes通过watch的机制进行每个组件的协作,每个组件之间的设计实现了解耦。
Pod的status字段是一个PodStatus对象,PodStatus中有一个phase字段
参考资料来源: debian.cn/articles/69…
apiVersion: v1 #版本号
kind: Pod #资源对象类型,还有其他可选的类型
metadata: #元数据
name: string #pod的名称
namespace: string #pod所属的命名空间
labels: #自定义标签列表
- name: string
annotations: #自定义注解列表
- name: string
spec: #pod基于那个的容器来创建的详细定义
containers:
- name: string #容器的名称
image: string #容器的镜像
imagePullPolicy: [Always|Never|IfNotPresent] #容器镜像拉取策略
command: [string] #容器的启动命令列表
args: [string] #启动命令参数
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string
mountPath: string #挂载的目录
readOnly: boolean #是否只读挂载
ports: #容器暴露的端口列表
- name: string #端口名称
containerPort: int #容器监听的端口
hostPort: int #容器所在主机需要监听的端口
protocol: string #端口协议
env: #容器中的环境变量
- name: string
value: string
resources: #资源限制设置
limits: #最大使用资源
cpu: string
memory: string
requests: #请求时资源设置
cpu: string
memory: string
livenessProbe: #对容器的健康检查
exec: #通过命令的返回值
command: [string]
httpGet: #通过访问容器的端口的返回的状态码
path: string
port: number
host: string
scheme: string
httpHeaders:
- name: string
value: string
tcpSocket: #通过tcpSocket
port: number
initialDelaySeconds: 0 #首次健康检查时间
timeoutSeconds: 0 #健康检查的超时时间
periodSeconds: 0 #每次健康检查的时间间隔
successThreshold: 0
failureThreshold: 0
securityContext:
privileged: false
restartPolicy: [Always|Never|OnFailure] #pod的重启策略
nodeSelector: object #运行节点的选择器,给节点设置标签后可以指定的运行pod的node标签
imagePullSecrets:
- name: string
hostNetwork: false #是否使用主机网络模式
volumes: #该pod上定义的共享存储卷列表
- name: string
emptyDir: {} #临时挂载
hostPath: #挂载宿主机目录
path: string
secret: #类型为secret存储卷
secretName: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷
name: string
items:
- key: string
path: string
复制代码
7.Pod 一个简单的配置示例:
顶一个pod的yaml文件信息 mypodtest.yaml:
apiVersion: v1
kind: Pod
metadata:
name: pod-xiaozhong-test
namespace: default
labels:
app: mybusybox
spec:
containers:
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "sleep 10"
复制代码
然后应用:
[root@k81-master01 k8s-install]# kubectl apply -f mypodtest.yaml
pod/pod-xiaozhong-test created
[root@k81-master01 k8s-install]#
复制代码
然后查看pod:
[root@k81-master01 k8s-install]# kubectl get pods
NAME READY STATUS RESTARTS AGE
chaoge-nginx-586ddcf5c4-bg8f4 1/1 Running 0 2d20h
nginx-deployment-574b87c764-47vpw 1/1 Running 0 2d19h
nginx-deployment-574b87c764-745gt 1/1 Running 0 6d16h
nginx-deployment-574b87c764-cz548 1/1 Running 0 2d19h
nginx-deployment-574b87c764-j9bps 1/1 Running 0 2d19h
nginx-deployment-574b87c764-ldtj6 1/1 Running 0 2d19h
pod-xiaozhong-test 0/1 Completed 1 51s
zyx-nginx-5c559d5697-dhz2z 1/1 Running 0 8d
zyx-nginx-5c559d5697-qvkjl 1/1 Running 0 2d19h
[root@k81-master01 k8s-install]#
复制代码
如使用nodeName调度示例:
先删除上一个简单的示例:
[root@k81-master01 k8s-install]# kubectl delete pod pod-xiaozhong-test
pod "pod-xiaozhong-test" deleted
[root@k81-master01 k8s-install]#
复制代码
在创建重新配置我们的yaml文件并添加指定的节点192.168.219.140(node3节点):
apiVersion: v1
kind: Pod
metadata:
name: pod-xiaozhong-test
namespace: default
labels:
app: mybusybox
spec:
nodeName: 192.168.219.140
containers:
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "sleep 60"
复制代码
然后再应用:
[root@k81-master01 k8s-install]# kubectl apply -f mypodtest.yaml
pod/pod-xiaozhong-test created
[root@k81-master01 k8s-install]#
复制代码
查看pod信息:
修改为使用节点的名称,而不是使用ip:
apiVersion: v1
kind: Pod
metadata:
name: pod-xiaozhong-test
namespace: default
labels:
app: mybusybox
spec:
nodeName: k81-node03
containers:
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "sleep 60"
复制代码
再查看应用:
查看pod执行的日志明细:
[root@k81-master01 k8s-install]# kubectl describe pod pod-xiaozhong-test
Name: pod-xiaozhong-test
Namespace: default
Priority: 0
Node: k81-node03/192.168.219.140
Start Time: Fri, 10 Sep 2021 11:08:40 0800
Labels: app=mybusybox
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"mybusybox"},"name":"pod-xiaozhong-test","namespace":"default...
Status: Running
IP: 10.244.2.17
IPs:
IP: 10.244.2.17
Containers:
busybox:
Container ID: docker://c9b0c40d8f6315dd062a89119c0c14803891af17fc71ba9a265bdf30eec65136
Image: busybox:latest
Image ID: docker-pullable://busybox@sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
sleep 60
State: Running
Started: Fri, 10 Sep 2021 11:12:54 0800
Last State: Terminated
Reason: Completed
Exit Code: 0
Started: Fri, 10 Sep 2021 11:11:22 0800
Finished: Fri, 10 Sep 2021 11:12:22 0800
Ready: True
Restart Count: 3
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-m4qkm (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-m4qkm:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-m4qkm
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning BackOff 74s (x3 over 2m46s) kubelet, k81-node03 Back-off restarting failed container
Normal Pulling 62s (x4 over 5m6s) kubelet, k81-node03 Pulling image "busybox:latest"
Normal Pulled 56s (x4 over 4m52s) kubelet, k81-node03 Successfully pulled image "busybox:latest"
Normal Created 56s (x4 over 4m52s) kubelet, k81-node03 Created container busybox
Normal Started 56s (x4 over 4m52s) kubelet, k81-node03 Started container busybox
[root@k81-master01 k8s-install]#
复制代码
还可以查看日志记录:
还可以([root@k81-master01 k8s-install]# kubectl logs pod-xiaozhong-test
)
复制代码
9.Pod钩子
容器钩子两类触发点:
PostStart
PreStop
定义文件mypodpoststart.yaml:
apiVersion: v1
kind: Pod
metadata:
name: pod-xiaozhong-poststart
namespace: default
labels:
app: mybusybox
spec:
containers:
- name: busybox
image: busybox:latest
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c"]
command:
- "/bin/sh"
- "-c"
复制代码
执行并查看结果:
# 应用执行
[root@k81-master01 k8s-install]# kubectl apply -f mypodpoststart.yaml
pod/pod-xiaozhong-poststart created
# 日志查看
[root@k81-master01 k8s-install]# kubectl logs pod-xiaozhong-
pod-xiaozhong-poststart pod-xiaozhong-test
[root@k81-master01 k8s-install]# kubectl logs pod-xiaozhong-
pod-xiaozhong-poststart pod-xiaozhong-test
[root@k81-master01 k8s-install]# kubectl logs pod-xiaozhong-poststart
/bin/sh: -c requires an argument
# 明细查看
[root@k81-master01 k8s-install]# kubectl describe pod pod-xiaozhong-poststart
Name: pod-xiaozhong-poststart
Namespace: default
Priority: 0
Node: k81-node02/192.168.219.139
Start Time: Fri, 10 Sep 2021 11:28:29 0800
Labels: app=mybusybox
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"app":"mybusybox"},"name":"pod-xiaozhong-poststart","namespace":"de...
Status: Running
IP: 10.244.1.33
IPs:
IP: 10.244.1.33
Containers:
busybox:
Container ID: docker://f638f100e976ab2641b3f98f478e332c7cbf40bc2553518451ff4aef20c4e626
Image: busybox:latest
Image ID: docker-pullable://busybox@sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
State: Waiting
Reason: PostStartHookError: rpc error: code = Unknown desc = container not running (f638f100e976ab2641b3f98f478e332c7cbf40bc2553518451ff4aef20c4e626)
Last State: Terminated
Reason: Error
Exit Code: 2
Started: Fri, 10 Sep 2021 11:29:09 0800
Finished: Fri, 10 Sep 2021 11:29:09 0800
Ready: False
Restart Count: 2
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-m4qkm (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-m4qkm:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-m4qkm
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/pod-xiaozhong-poststart to k81-node02
Normal Pulling 15s (x3 over 48s) kubelet, k81-node02 Pulling image "busybox:latest"
Normal Pulled 10s (x3 over 43s) kubelet, k81-node02 Successfully pulled image "busybox:latest"
Normal Created 10s (x3 over 43s) kubelet, k81-node02 Created container busybox
Normal Started 9s (x3 over 43s) kubelet, k81-node02 Started container busybox
Warning FailedPostStartHook 9s (x3 over 43s) kubelet, k81-node02 Exec lifecycle hook ([/bin/sh -c echo 1 > /tmp/message]) for Container "busybox" in Pod "pod-xiaozhong-poststart_default(e25ea0a3-49fc-4407-a4ef-c35bccc4d875)" failed - error: rpc error: code = Unknown desc = container not running (busybox), message: ""
Normal Killing 9s (x3 over 43s) kubelet, k81-node02 FailedPostStartHook
Warning BackOff 9s (x3 over 30s) kubelet, k81-node02 Back-off restarting failed container
[root@k81-master01 k8s-install]#
复制代码
查看容器状态:显示容器已异常退出:
10.Pod探针(存活探测机制)- ExecAction:容器内执行指定命令。如果命令执行结束退出时返回码为0则认为诊断成功。
- TCPSocketAction:对指定端口上的容器的IP地址进行TCP健康检查。如果端口打开,则诊断被认为是成功的。
- HTTPGetAction:对指定的端口和路径上的容器的IP地址执行HTTPGet请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功。
复制代码
10.1.2 诊断结果
- 成功:容器通过了诊断。
- 失败:容器未通过诊断。
- 未知:诊断失败,不会采取任何行动
复制代码
10.2 探针的方式:10.2.1startupProbe探针 (启动检查):
- 用于判断**容器内应用程序是否已经启动**,如果配置了startuprobe,就会先禁用其他的探测,直到它成功为止,成功后将不再进行探测,这个是对一个Pod启动情况的检查机制。
复制代码
10.2.2livenessProbe探针(存活检查):
- 探测的是**容器是否运行**
- 根据用户自定义规则来判定pod对象健康状态,如果livenessProbe探针探测到容器不健康,则kubelet会根据启动的时候Pod重启策略来决定当前的不健康的Pod是否重启
- 如果一个容器不包含livenessProbe探针,则kubelet会认为容器的livenessProbe探针的返回值永远成功。
复制代码
10.2.3ReadinessProbe探针 (就绪检查):
- 探测的是的**容器内的程序健康**情况,如果它的返回值为success,那么就代表这个容器已经完成启动,且程序已处于可以接受流量的状态.
- 根据用户自定义规则来判定pod对象健康状态,如果探测失败,控制器会将此pod从对应service的endpoint列表中移除,从此不再将任何请求分发调度到这个Pod上,直至下次探测成功为止。
复制代码
10.2.4 一些探针参数值说明
initialDelaySeconds:默认值是0,最小值是0,容器启动后等待多久,liveness or readiness开始第1次执行
periodSeconds:多久执行一次探针,默认值是10,最小值是1
timeoutSeconds:探针执行超时时间,默认值是1,最小值是1
successThreshold:失败后执行多少次探针成功才算成功,默认值是1,最小值是1,对于liveness来说必须是1
failureThreshold:探针连续失败多少次后才算失败,默认是3,最小值是1
复制代码
11.Pod的restartPolicy重启策略机制
一个pod运行过程中,当一个容器执行完成后退出时,不管是成功还是失败,都会触发重启策略,pod会根据restartPolicy的设置参数值来决定要不要重启该容器,restartPolicy有以下3种取值:
Always:是默认取值,不管是成功退出还是失败退出,都尝试重启该容器,Pod的阶段会保持为Running OnFailure:限于失败的时候重启,Pod的阶段保持为Running,成功的时候不重启,Pod的阶段转为Succeeded Never:不管失败还是成功都不重启,Pod的阶段都转为Failed或者Succeeded 当一个Pod退出后要重启时,有一段指数级递增的延迟(10s,20s,40s…最大达到5分钟),当一个容器重启并运行10分钟不出问题后,这个延迟会重置。
12.Pod的删除和回收12.1 删除来源参考资料:kubernetes.io/docs/concep…
12.2 回收来源参考资料:kubernetes.io/docs/concep…
主要作用:
同一个文件里面创建一组相关的服务如:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myNginx
labels:
app: myNginx
spec:
replicas: 3
template:
metadata:
name: myNginx
labels:
app: myNginx
spec:
containers:
- name: myNginx
image: icepear/myNginx:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
restartPolicy: Always
selector:
matchLabels:
app: myNginx
---
apiVersion: v1
kind: Service
metadata:
name: nginxService
spec:
selector:
app: myNginx
ports:
- port: 80
targetPort: 80
protocol: TCP
type: NodePort
复制代码
2、服务对象分类(个人理解梳理)
默认的情况我们的yaml不知道的创建的service类型的时候就是默认的ClusterIp,ClusterIp其实可以理解为就一个VIP(Virtual IP Address,虚拟IP地址)
apiVersion: v1
kind: Service
metadata:
name: xiaozhong-nginx-clusterip
namespace: default
labels:
app: nginx
spec:
ports: # 指定端口
- name: socket
port: 8828 # 暴露给服务的端口
targetPort: 8828 #目标端口,容器的端口
protocol: TCP
selector: # 标签选择器,知道选择要关联的Pod资源标签
app: nginx
type: ClusterIP #指定服务类型为ClusterIP,默认不写就是这样类型
复制代码
1.2 查看资源的明细:
[root@k81-master01 k8s-install]# kubectl describe svc xiaozhong-nginx-clusterip
Name: xiaozhong-nginx-clusterip
Namespace: default
Labels: app=nginx
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"xiaozhong-nginx-clusterip","namespace":"...
Selector: app=nginx
Type: ClusterIP
IP: 10.99.170.220 # 这个地方就是服务的虚拟IP
Port: socket 8828/TCP
TargetPort: 8828/TCP
Endpoints: 10.244.1.19:8828,10.244.1.20:8828,10.244.2.10:8828 4 more... # 后端管理的Pod相关的IP和端口
Session Affinity: None
Events: <none>
[root@k81-master01 k8s-install]#
复制代码
1.3 关于Session Affinity,Pod的会话保持
从上面查看我们的服务资源明细中有一个项是关于Session Affinity,它的主要作用就是对于同一个客户端的请求的处理的会话保持的机制。
会话保持就是:当我们的一个请求依赖于一些客户端的身份信息等来请求知道的某个Pod的时候,固定的调度某个Pod的时候,责可以启动这个粘性会话机制。
1:创建服务类型clusterIP之后, clusterIP在每个 node 节点使用 iptables,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中。
2:然后 基于kube-proxy 自己内部实现负载均衡的方法,查询到对应service 下对应 pod 的地址和端口,进而把数据转发给对应的 pod 的地址和端口
2、基于ClusterIP 基础上-NodePort类型访问基于 ClusterIP 基础上为 Service 在每台机器上绑定一个端口, 这样就可以通过<NodeIP>:NodePort 来访问该SVC后端的80的pod组服务!
NodePort类型(接入集群外部请求,如集群需外部访问,但仅限于访问节点)
2.1 定义NodePort类型服务PS:此服务类型再安装K8S的使用已经预留一个端口范围用于NodePort,默认的端口范围是:30000-32767之间
xiaozhong-nginx-nodeport.yaml文件:
apiVersion: v1
kind: Service
metadata:
name: xiaozhong-nginx-nodeprt
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- name: http
port: 8000
protocol: TCP
targetPort: 80
type: NodePort
复制代码
2.2 创建服务和查看
[root@k81-master01 k8s-install]# kubectl apply -f xiaozhong-nginx-nodeport.yaml
service/xiaozhong-nginx-nodeprt created
[root@k81-master01 k8s-install]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d2h <none>
xiaozhong-nginx-nodeprt NodePort 10.102.138.39 <none> 8000:30595/TCP 102s app=nginx
[root@k81-master01 k8s-install]#
复制代码
2.3 外网访问验证
每个节点都去访问:
好像Nodeport也可以启动类似负载均衡器类型的作用啊!有点奇怪!估计我的理解还是有点偏差!后续继续再补充!
简图的图示:
2.4 数据转发流程理解:1: 创建nodePort服务类型后, 则在 node 上开启一个随机(或指定的)端口,
2:访问Nodeip:nodePort的时候将向该端口的流量导入到 kube-proxy
3:然后由 kube-proxy 进一步(与接口层交互)到给对应的 pod
3、LoadBalancer:基于NodePort 的基础上的-LoadBalancer类型的Service服务部署创建的示例回顾这种类型其实可以理解为:在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到<NodeIP>:NodePort,
loadBalancer和nodePort其实是同一种方式。主要区别点在于 :loadBalancer比nodePort多了一步,就是可以调用cloud provider去创建LB(阿里云SLB)来向节点导流
从最初开始部署一个Nginx应用示例的时候,我们就开始其实开启了一个默认的LoadBalancer类型的Service,现在重新回顾一下当时的具体流程。
1、应用和服务创建流程编写一个deployment的yaml部署文件xiaozhong-nginx-dev.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: xiaozhong-nginx
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
复制代码
[root@k81-master01 k8s-install]# kubectl apply -f xiaozhong-nginx-dev.yaml
deployment.apps/xiaozhong-nginx created
[root@k81-master01 k8s-install]#
复制代码
[root@k81-master01 k8s-install]# kubectl get pods -o wide |grep xiaozhong
xiaozhong-nginx-5c559d5697-cfcxx 1/1 Running 0 4s 10.244.1.30 k81-node02 <none> <none>
xiaozhong-nginx-5c559d5697-jtfbs 1/1 Running 0 4s 10.244.1.31 k81-node02 <none> <none>
[root@k81-master01 k8s-install]#
复制代码
两个Pod都运行再了Node2节点上!!
全部节点访问验证: 在master和在Node2和Node3节点上访问:
PS:目前仅限于当前集群上内网内的访问,外部是无法访问
[root@k81-master01 k8s-install]# curl 10.244.1.31
[root@k81-master01 k8s-install]# curl 10.244.1.30
[root@k81-node02 ~]# curl 10.244.1.30
[root@k81-node02 ~]# curl 10.244.1.31
[root@k81-node03 ~]# curl 10.244.1.31
[root@k81-node03 ~]# curl 10.244.1.30
复制代码
响应的结果:
结果都返回:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@k81-master01 k8s-install]#
复制代码
[root@k81-master01 k8s-install]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d1h <none>
[root@k81-master01 k8s-install]#
复制代码
[root@k81-master01 k8s-install]# kubectl expose deployment xiaozhong-nginx --port=80 --type=LoadBalancer
service/xiaozhong-nginx exposed
[root@k81-master01 k8s-install]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d1h <none>
xiaozhong-nginx LoadBalancer 10.98.134.172 <pending> 80:32610/TCP 5s app=nginx
[root@k81-master01 k8s-install]#
复制代码
查看我们的SVC明细:
[root@k81-master01 k8s-install]# curl 10.98.134.172
[root@k81-node02 ~]# curl 10.98.134.172
[root@k81-node03 ~]# curl 10.98.134.172
复制代码
如访问如下任意节点访问都可以访问成功:
[root@k81-master01 k8s-install]# curl 192.168.219.138:32610
[root@k81-node02 ~]# curl 192.168.219.138:32610
[root@k81-node03 ~]# curl 192.168.219.138:32610
[root@k81-node03 ~]# curl 192.168.219.139:32610
[root@k81-node03 ~]# curl 192.168.219.140:32610
复制代码
以上是一个简单的创建负载均衡器示例。
2、查看服务时候一些字段说明
[root@k81-master01 k8s-install]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d2h <none>
xiaozhong-nginx LoadBalancer 10.98.134.172 <pending> 80:32610/TCP 18m app=nginx
复制代码
[root@k81-master01 k8s-install]# kubectl describe svc xiaozhong-nginx
Name: curl
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: LoadBalancer
IP: 10.98.134.172
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 32610/TCP
Endpoints: 10.244.1.19:80,10.244.1.20:80,10.244.1.30:80 6 more...
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
[root@k81-master01 k8s-install]#
复制代码
4、服务代理的Pod信息
[root@k81-master01 k8s-install]# kubectl get endpoints xiaozhong-nginx
NAME ENDPOINTS AGE
xiaozhong-nginx 10.244.1.19:80,10.244.1.20:80,10.244.1.30:80 6 more... 24m
[root@k81-master01 k8s-install]#
复制代码
5、删除服务
[root@k81-master01 k8s-install]# kubectl delete -f xiaozhong-nginx-dev.yaml
deployment.apps "xiaozhong-nginx" deleted
[root@k81-master01 k8s-install]#
[root@k81-master01 k8s-install]# kubectl delete -f xiaozhong-nginx-dev.yaml
Error from server (NotFound): error when deleting "xiaozhong-nginx-dev.yaml": deployments.apps "xiaozhong-nginx" not found
[root@k81-master01 k8s-install]# ^C
[root@k81-master01 k8s-install]#
这种方式实践好像删除不了!
再查看服务信息的时候没删除!情况未知!
[root@k81-master01 k8s-install]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d2h
xiaozhong-nginx LoadBalancer 10.98.134.172 <pending> 80:32610/TCP 38m
[root@k81-master01 k8s-install]#
复制代码
[root@k81-master01 k8s-install]# kubectl delete svc xiaozhong-nginx
service "xiaozhong-nginx" deleted
[root@k81-master01 k8s-install]#
[root@k81-master01 k8s-install]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d2h
[root@k81-master01 k8s-install]#
复制代码
上面的示例还只是一个简单的IP端看示例!
4、 创建ExternalName service4.1 定义ExternalName类型服务PS:此主机名需要被DNS服务解析成CNAME 类型的记录,且此类似的服务对象其无clusterIP 和 Noport,也没有标签选择器,因此没endpoints ,其是一个域名,是CNAME结构,用于集群内部的域名
xiaozhong-nginx-ext.yaml文件:
apiVersion: v1
kind: Service
metadata:
name: xiaozhong-nginx-externa
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- name: http
port: 8001
protocol: TCP
targetPort: 80
type: ExternalName
externalName: zyx.xiaozhong.cn
复制代码
4.2 创建服务和查看
[root@k81-master01 k8s-install]# kubectl apply -f xiaozhong-nginx-ext.yaml
service/xiaozhong-nginx-externa created
[root@k81-master01 k8s-install]# ^C
[root@k81-master01 k8s-install]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d3h <none>
xiaozhong-nginx-externa ExternalName <none> zyx.xiaozhong.cn 8001/TCP 65s app=nginx
xiaozhong-nginx-nodeprt NodePort 10.102.138.39 <none> 8000:30595/TCP 20m app=nginx
[root@k81-master01 k8s-install]#
复制代码
注意看这地方的外部的IP信息:
4.3 访问验证(因为我的域名是随便写的)在集群内访问这个域名的时候提示没权限信息
[root@k81-master01 k8s-install]# curl zyx.xiaozhong.cn
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
Sorry for the inconvenience.<br/>
Please report this message and include the following information to us.<br/>
Thank you very much!</p>
<table>
<tr>
<td>URL:</td>
<td>http://zyx.xiaozhong.cn/</td>
</tr>
<tr>
<td>Server:</td>
<td>izj6c7rml031xf17m0lnliz</td>
</tr>
<tr>
<td>Date:</td>
<td>2021/09/08 16:36:44</td>
</tr>
</table>
<hr/>Powered by Tengine/2.3.2<hr><center>tengine</center>
</body>
</html>
[root@k81-master01 k8s-install]#
复制代码
5、 创建 Headless Service资源类型(无头服务)
无头服务类型的理解:
如果客户端需要直接的访问service资源后端的所有POD资源,此时则需要向客户端暴露每个Pod对象的IP地址,而不是使用中间层service对象类型中的的ClusterIP的IP地址。 这种的服务可以定义是一个无头的服务类型!
特点:
这里暂时理解的还不是很透!!!以后再深入理解一下!!!
5.1 定义Headless Service类型服务apiVersion: v1
kind: Service
metadata:
name: demo-service # service名称
spec:
clusterIP: None #指定其类型为Headless Service资源
selector: # 用于匹配后面POD对象
app: service
ports:
- protocol: TCP # 使用的协议
port: 80 #定义暴露的端口
targetPort: 80 # 后端POD端口号
name: httpport # 定义名字
复制代码
三、Service 三种代理模式
首先我们的再之前的NodePort类型服务中我们的了解到,我们这种是在每个Node工作节点的上暴露我们的NodePort节点的方式来提供访问Nodeip:NodePort来访问我们的Pod的服务。
那如果我们的需要统一访问的路口处,使用域名的方式来规划我们的访问呐?这时候该如何的处理呢?
引入Ingress,Ingress也是Kubernetes中为了使外部的应用能够访问集群内的服务,在提供了以下一种方案:
以下下主要大部分文字来源主要是参考:blog.csdn.net/zhangjunli/…
4.1 Ingress 的组成4.2 Ingress 工作原理PS: ingress controller 可以有多种的实现,不一定是使用Nginx
ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS能力以及基于host的方向代理,ingress要依靠ingress-controller来具体实现以上功能。
1.ingress controller,的形式其实就是都是一个pod,里面跑着daemon程序和反向代理程序,它通过和kubernetes api交互,动态的去感知集群中ingress规则变化。
2.然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置
3.再写到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中
4.然后reload一下使配置生效。以此达到域名分配置和动态更新的问题。
4.3 Ingress 解决什么问题ingress可以简单理解为service的service,它通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。
如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要而外的操作. 这种处理方式可以吧服务和请求进行解耦,可以从业务维护统一角度考虑业务暴露,不需要再为每个service单独考虑。
4.4 Ingress 可选控制器类型PS: 1:Ingress通常不会公开任意端口和协议!
PS: 2:向 Internet 公开 HTTP 和 HTTPS 以外的服务通常Service.Type类型是:NodePort
前提理解要点:
PS:关于DaemonSet类型的资源后续会展开,这里先做一个简单的介绍:
1:DaemonSet类型它也是一种Pod控制器。
2:它的特点是:会在每一个Node节点上都会生成并且只能生成一个Pod资源。
3:使用场景:如果必须将Pod运行在固定的某个或某几个节点,且要优先于其他Pod的启动。
4:通常情况下,默认每一个节点都会运行,并且只能运行一个Pod。这种情况推荐使用DaemonSet资源对象。比如我们的普罗米修斯的采集信息,都需要在每个节点进行采集。就合适使用这种类型Pod.
问题点思考:
上述的问题点是:我们的外部访问依赖使用Nodeip:NodePort(service暴露的端口)的方式,那我们的能不能统一的使用一个域名的方式来做统一的访问入口呐?
4.4 Ingress 安装部署示例验证说明blog.csdn.net/yujia_666/a…
来自官网的安装部署步骤: kubernetes.github.io/ingress-ngi…
4.4.1 Ingress 常见的部署和暴露方式:Deployment LoadBalancer模式的ServicePS:以下的文字来自blog.csdn.net/yujia_666/a…
如果要把ingress部署在公有云,那用这种方式比较合适。用Deployment部署ingress-controller,创建一个type为LoadBalancer的service关联这组pod。大部分公有云,都会为LoadBalancer的service自动创建一个负载均衡器,通常还绑定了公网地址。只要把域名解析指向该地址,就实现了集群服务的对外暴露。
Deployment NodePort模式的Service同样用deployment模式部署ingress-controller,并创建对应的服务,但是type为NodePort。这样,ingress就会暴露在集群节点ip的特定端口上。由于nodeport暴露的端口是随机端口,一般会在前面再搭建一套负载均衡器来转发请求。该方式一般用于宿主机是相对固定的环境ip地址不变的场景。
NodePort方式暴露ingress虽然简单方便,但是NodePort多了一层NAT,在请求量级很大时可能对性能会有一定影响。
用DaemonSet结合nodeselector来部署ingress-controller到特定的node上,然后使用HostNetwork直接把该pod与宿主机node的网络打通,直接使用宿主机的80/433端口就能访问服务。这时,ingress-controller所在的node机器就很类似传统架构的边缘节点,比如机房入口的nginx服务器。该方式整个请求链路最简单,性能相对NodePort模式更好。缺点是由于直接利用宿主机节点的网络和端口,一个node只能部署一个ingress-controller pod。比较适合大并发的生产环境使用。
作者:小钟同学
链接:https://juejin.cn/post/7006149882427736071
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved