虽然 Docker 已经很强大了,可是在实际使用上仍是有诸多不便,好比集群管理、资源调度、文件管理等等。那么在这样一个百花齐放的容器时代涌现出了不少解决方案,好比 Mesos、Swarm、Kubernetes 等等,其中谷歌开源的 Kubernetes 是做为老大哥的存在。html
kubernetes 已经成为容器编排领域的王者,它是基于容器的集群编排引擎,具有扩展集群、滚动升级回滚、弹性伸缩、自动治愈、服务发现等多种特性能力。node
服务发现和负载均衡mysql
存储编排linux
自动部署和回滚nginx
自动二进制打包git
自我修复web
密钥与配置管理面试
Kubernetes 的出现不只主宰了容器编排的市场,更改变了过去的运维方式,不只将开发与运维之间边界变得更加模糊,并且让 DevOps 这一角色变得更加清晰,每个软件工程师均可以经过 Kubernetes 来定义服务之间的拓扑关系、线上的节点个数、资源使用量而且可以快速实现水平扩容、蓝绿部署等在过去复杂的运维操做。redis
主要介绍学习一些什么知识算法
传统的客户端服务端架构
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 的一些基本概念
主要由如下几个核心组件组成:
apiserver
controller manager
scheduler
etcd
kubelet
kube-proxy
Container runtime
除了核心组件,还有一些推荐的插件:
CoreDNS
Dashboard
Ingress Controller
Prometheus
Federation
以上内容参考连接: https://www.escapelife.site/p...
安装v1.16.0版本,居然成功了。记录在此,避免后来者踩坑。
本篇文章,安装大步骤以下:
详细安装步骤参考:CentOS 搭建 K8S,一次性成功,收藏了!
集群安装教程请参考:全网最新、最详细基于V1.20版本,无坑部署最小化 K8S 集群教程
Pod 就是最小而且最简单的 Kubernetes 对象
Pod、Service、Volume 和 Namespace 是 Kubernetes 集群中四大基本对象,它们可以表示系统中部署的应用、工做负载、网络和磁盘资源,共同定义了集群的状态。Kubernetes 中不少其余的资源其实只对这些基本的对象进行了组合。
详细介绍请参考:Kubernetes 之 Pod 实现原理
Kuternetes 企业级 Docker 私有仓库 Harbor 工具。
Harbor 的每一个组件都是以 Docker 容器的形式构建的,使用 Docker Compose 来对它进行部署。用于部署 Harbor 的 Docker Compose 模板位于 /Deployer/docker-compose.yml 中,其由 5 个容器组成,这几个容器经过 Docker link 的形式链接在一块儿,在容器之间经过容器名字互相访问。对终端用户而言,只须要暴露 Proxy(即Nginx) 的服务端口便可。
Proxy
Registry
UI
MySQL
Log
详细介绍与搭建步骤请参考:企业级环境中基于 Harbor 搭建
YAML 是一种很是简洁/强大/专门用来写配置文件的语言!
YAML 全称是 ”YAML Ain’t a Markup Language” 的递归缩写,该语言的设计参考了 JSON / XML 和 SDL 等语言,强调以数据为中心,简洁易读,编写简单。
学过编程的人理解起来应该很是容易
推荐给你们一篇文章:Kubernetes 之 YAML 语法,这篇文章介绍的很是详细,有不少例子说明。
K8S 中全部的内容都抽象为了资源,资源实例化以后就叫作对象。
在 Kubernetes 系统中,Kubernetes 对象是持久化的实体,Kubernetes 使用这些实体去表示整个集群的状态。特别地,它们描述了以下信息:
Kubernetes 对象是 “目标性记录” —— 一旦建立对象,Kubernetes 系统将持续工做以确保对象存在。经过建立对象,本质上是在告知 Kubernetes 系统,所须要的集群工做负载看起来是什么样子的,这就是 Kubernetes 集群的指望状态。
Kubernetes 资源控制器配置文件的编写是学习 K8S 的重中之重!
资源配额控制器确保了指定的资源对象始终不会超过配置的资源,可以有效的下降整个系统宕机的机率,加强系统的鲁棒性,对整个集群的稳定性有很是重要的做用。
Kubernetes 中为了实现服务实例间的负载均衡和不一样服务间的服务发现,创造了 Service 对象,同时又为从集群外部访问集群建立了 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 是 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
kubectl create -f <目录>
kubectl create -f https://git.io/vPieo
kubectl get nodes kubectl get namespace
# 查看子命令帮助信息 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
kubectl get rc
# 查看所有deployment kubectl get deployment # 列出指定deployment kubectl get deployment my-app
kubectl get svc kubectl get service
kubectl get pods -n default kubectl get pods --all-namespace
kubectl describe pods/nginx kubectl describe pods my-pod kubectl describe -f pod.json
kubectl describe nodes c1
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 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
# yaml文件名字按照你建立时的文件一致 kubectl delete -f xxx.yaml
kubectl delete pods -l name=<label-name>
kubectl delete services -l name=<label-name>
kubectl delete pods,services -l name=<label-name>
kubectl delete pods --all kubectl delete service --all kubectl delete deployment --all
在编辑器中编辑任何 API 资源
# 编辑名为docker-registry的service kubectl edit svc/docker-registry
在寄主机上,不进入容器直接执行命令
kubectl exec mypod -- date kubectl exec mypod --namespace=test -- 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正在不断加快在云原生环境的应用,但如何以统1、安全的方式对运行于任何地方的Kubernetes集群进行管理面临着挑战,而有效的管理工具可以大大下降管理的难度。
k9s是基于终端的资源仪表板。它只有一个命令行界面。不管在Kubernetes仪表板Web UI上作什么,均可以在终端使用K9s仪表板工具进行相同的操做。k9s持续关注Kubernetes集群,并提供命令以使用集群上定义的资源。
使用Kubernetes的一些策略,在安全性、监控、网络、治理、存储、容器生命周期管理和平台选择方面应用最佳实践。下面让咱们来看看Kubernetes的一些生产最佳实践。在生产中运行Kubernetes并不容易; 有如下几个方面须要注意。
管理大型分布式系统可能会很复杂,特别是当出现问题时,咱们没法及时获得通知。为了确保应用实例正常工做,设置Kubernetes健康检查相当重要。
经过建立自定义运行健康检查,能够有效避免分布式系统中僵尸服务运行,具体能够根据环境和须要对其进行调整。
就绪探针的目的是让Kubernetes知道该应用是否已经准备好为流量服务。Kubernetes将始终确保准备就绪探针经过以后开始分配服务,将流量发送到Pod。
你怎么知道你的应用程序是活的仍是死的?存活探针可让你作到这一点。若是你的应用死了,Kubernetes会移除旧的Pod并用新Pod替换它。
为单个容器指定资源请求和限制是一个很好的实践。另外一个好的实践是将Kubernetes环境划分为不一样团队、部门、应用程序和客户机的独立名称空间。
Kubernetes资源使用指的是容器/pod在生产中所使用的资源数量。
所以,密切关注pods的资源使用状况是很是重要的。一个明显的缘由是成本,由于越高的资源利用证实越少的资源浪费。
Ops团队一般但愿优化和最大化pods消耗的资源百分比。资源使用状况是Kubernetes环境实际优化程度的指标之一。
您能够认为优化后的Kubernetes环境中运行的容器的平均CPU等资源利用率是最优的。
RBAC表明基于角色的访问控制。它是一种用于限制系统/网络上的用户和应用程序的访问和准入的方法。他们从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插件,以提供负载均衡能力。
标签就像附加到对象上的键/值对,好比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,所以必须遵循上面提到的最佳实践,以顺利和可靠地扩展应用程序。
内容来源:https://my.oschina.net/u/1787...
对于新安装的 Kubernetes,常常出现的一个问题是 Service 没有正常工做。若是您已经运行了 Deployment 并建立了一个 Service,可是当您尝试访问它时没有获得响应,但愿这份文档(全网最详细的 K8s 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
rm -rf /var/lib/etcd/*
删除后从新 reboot master 结点。
reset etcd 后须要从新设置网络 etcdctl mk /atomic.io/network/config '{ "Network": "192.168.0.0/16" }'
每次启动都是报以下问题:
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.
在配置 fluentd 时候出现cannot create /var/log/fluentd.log: Permission denied 错误,这是由于没有关掉 SElinux 安全致使。
能够在 /etc/selinux/config 中将 SELINUX=enforcing 设置成 disabled,而后 reboot
首先生成各类须要的 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是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,而后就能够启动啦!
问题背景:当前部署了 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
在每台服务器须要创建主机互信的用户名执行如下命令生成公钥/密钥,默认回车便可
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)
hostnamectl set-hostname k8s-master1
若是不安装或者不输出,能够将 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
能够经过下面命令强制删除
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
下面咱们建立一个对应的容器,该容器只有 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 规则。
来源:https://www.cnblogs.com/passz...
Kubernetes 上对应用程序进行故障排除的 6 个技巧 推荐给你们,平常排错必备。分享一份阿里云内部超全K8s实战手册,免费下载!
一个目标:容器操做;两地三中心;四层服务发现;五种 Pod 共享资源;六个 CNI 经常使用插件;七层负载均衡;八种隔离维度;九个网络模型原则;十类 IP 地址;百级产品线;千级物理机;万级容器;相如无亿,k8s 有亿:亿级日服务人次。
Kubernetes(k8s)是自动化容器操做的开源平台。这些容器操做包括:部署、调度和节点集群间扩展。
自动化容器部署和复制。
实时弹性收缩容器规模。
容器编排成组,并提供容器间的负载均衡。
调度:容器在哪一个机器上运行。
kubectl:客户端命令行工具,做为整个系统的操做入口。
kube-apiserver:以 REST API 服务形式提供接口,做为整个系统的控制入口。
kube-controller-manager:执行整个系统的后台任务,包括节点状态情况、Pod 个数、Pods 和Service 的关联等。
kube-scheduler:负责节点资源管理,接收来自 kube-apiserver 建立 Pods 任务,并分配到某个节点。
etcd:负责节点间的服务发现和配置共享。
kube-proxy:运行在每一个计算节点上,负责 Pod 网络代理。定时从 etcd 获取到 service 信息来作相应的策略。
kubelet:运行在每一个计算节点上,做为 agent,接收分配该节点的 Pods 任务及管理容器,周期性获取容器状态,反馈给 kube-apiserver。
DNS:一个可选的 DNS 服务,用于为每一个 Service 对象建立 DNS 记录,这样全部的 Pod 就能够经过 DNS 访问服务了。
下面是 k8s 的架构拓扑图:
两地三中心
两地三中心包括本地生产中心、本地灾备中心、异地灾备中心。
两地三中心要解决的一个重要问题就是数据一致性问题。
k8s 使用 etcd 组件做为一个高可用、强一致性的服务发现存储仓库。用于配置共享和服务发现。
它做为一个受到 Zookeeper 和 doozer 启发而催生的项目。除了拥有他们的全部功能以外,还拥有如下 4 个特色:
简单:基于 HTTP+JSON 的 API 让你用 curl 命令就能够轻松使用。
安全:可选 SSL 客户认证机制。
快速:每一个实例每秒支持一千次写操做。
可信:使用 Raft 算法充分实现了分布式。
先一张图解释一下网络七层协议:
k8s 提供了两种方式进行服务发现:
环境变量:当建立一个 Pod 的时候,kubelet 会在该 Pod 中注入集群内全部 Service 的相关环境变量。须要注意的是,要想一个 Pod 中注入某个 Service 的环境变量,则必须 Service 要先比该 Pod 建立。这一点,几乎使得这种方式进行服务发现不可用。 好比,一个 ServiceName 为 redis-master 的 Service,对应的 ClusterIP:Port 为 10.0.0.11:6379,则对应的环境变量为:
DNS:能够经过 cluster add-on 的方式轻松的建立 KubeDNS 来对集群内的 Service 进行服务发现。
以上两种方式,一个是基于 TCP,DNS 基于 UDP,它们都是创建在四层协议之上。
Pod 是 k8s 最基本的操做单元,包含一个或多个紧密相关的容器。
一个 Pod 能够被一个容器化的环境看做应用层的“逻辑宿主机”;一个 Pod 中的多个容器应用一般是紧密耦合的,Pod 在 Node 上被建立、启动或者销毁;每一个 Pod 里运行着一个特殊的被称之为 Volume 挂载卷,所以他们之间通讯和数据交换更为高效。在设计时咱们能够充分利用这一特性将一组密切相关的服务进程放入同一个 Pod 中。
同一个 Pod 里的容器之间仅需经过 localhost 就能互相通讯。
一个 Pod 中的应用容器共享五种资源:
PID 命名空间:Pod 中的不一样应用程序能够看到其余应用程序的进程 ID。
网络命名空间:Pod 中的多个容器可以访问同一个IP和端口范围。
IPC 命名空间:Pod 中的多个容器可以使用 SystemV IPC 或 POSIX 消息队列进行通讯。
UTS 命名空间:Pod 中的多个容器共享一个主机名。
Volumes(共享存储卷):Pod 中的各个容器能够访问在 Pod 级别定义的 Volumes。
Pod 的生命周期经过 Replication Controller 来管理;经过模板进行定义,而后分配到一个 Node 上运行,在 Pod 所包含容器运行结束后,Pod 结束。
Kubernetes 为 Pod 设计了一套独特的网络配置,包括为每一个 Pod 分配一个IP地址,使用 Pod 名做为容器间通讯的主机名等。
CNI(Container Network Interface)容器网络接口是 Linux 容器网络配置的一组标准和库,用户须要根据这些标准和库来开发本身的容器网络插件。CNI 只专一解决容器网络链接和容器销毁时的资源释放,提供一套框架。因此 CNI 能够支持大量不一样的网络模式,而且容易实现。
下面用一张图表示六个 CNI 经常使用插件:
提负载均衡就不得不先提服务器之间的通讯。
IDC(Internet Data Center)也可称数据中心、机房,用来放置服务器。IDC 网络是服务器间通讯的桥梁。
上图里画了不少网络设备,它们都是干啥用的呢?
路由器、交换机、MGW/NAT 都是网络设备,按照性能、内外网划分不一样的角色。
外网核心路由器:经过静态互联运营商或 BGP 互联美团统一外网平台。
先说说各层负载均衡:
七层负载均衡:基于 URL 等应用层信息的负载均衡。
这里用一张图来讲说四层和七层负载均衡的区别:
上面四层服务发现讲的主要是 k8s 原生的 kube-proxy 方式。k8s 关于服务的暴露主要是经过 NodePort 方式,经过绑定 minion 主机的某个端口,而后进行 Pod 的请求转发和负载均衡,但这种方式有下面的缺陷:
Service 可能有不少个,若是每一个都绑定一个 Node 主机端口的话,主机须要开放外围的端口进行服务调用,管理混乱。
没法应用不少公司要求的防火墙规则。
理想的方式是经过一个外部的负载均衡器,绑定固定的端口,好比 80;而后根据域名或者服务名向后面的 Service IP 转发。
Nginx 很好的解决了这个需求,但问题是若是有的新的服务加入,如何去修改而且加载这些 Nginx 配置?
Kubernetes 给出的方案就是 Ingress。这是一个基于七层的方案。
k8s 集群调度这边须要对上面从上到下、从粗粒度到细粒度的隔离作相应的调度策略。
k8s 网络模型要符合四个基础原则、三个网络要求原则、一个架构原则、一个 IP 原则。
每一个 Pod 都拥有一个独立的 IP 地址,并且假定全部 Pod 都在一个能够直接连通的、扁平的网络空间中,无论是否运行在同一 Node 上均可以经过 Pod 的 IP 来访问。
k8s 中的 Pod 的 IP 是最小粒度 IP。同一个 Pod 内全部的容器共享一个网络堆栈,该模型称为 IP-per-Pod 模型。
Pod 由 docker0 实际分配的 IP。
Pod 内部看到的 IP 地址和端口与外部保持一致。
同一个 Pod 内的不一样容器共享网络,能够经过localhost来访问对方的端口,相似同一个虚拟机内不一样的进程。
IP-per-Pod 模型从端口分配、域名解析、服务发现、负载均衡、应用配置等角度看,Pod 能够看作是一台独立的虚拟机或物理机。
全部容器均可以不用 NAT 的方式同别的容器通讯。
全部节点均可以在不一样 NAT 方式下同全部容器通讯,反之亦然。
容器的地址和别人看到的地址是同一个地址。
要符合下面的架构:
由上图架构引伸出来 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 私有地址。 大量用于企业内部。保留这样的地址是为了不亦或是哪一个接入公网时引发地址混乱。
连接:blog.csdn.net/huakai_sun/article/details/82378856