Kubernetes(k8s)概述

开发理念
Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。

应用理念
k8s是一个编排容器的工具,其实也是管理应用的全生命周期的一个工具,从创建应用,应用的部署,应用提供服务,扩容缩容应用,应用更新,都非常的方便,而且可以做到故障自愈,例如一个服务器挂了,可以自动将这个服务器上的服务调度到另外一个主机上进行运行,无需进行人工干涉。

k8s可以更快的更新新版本,打包应用,更新的时候可以做到不用中断服务,服务器故障不用停机,从开发环境到测试环境到生产环境的迁移极其方便,一个配置文件搞定,一次生成image,到处运行

在k8s进行管理应用的时候,基本步骤是:创建集群,部署应用,发布应用,扩展应用,更新应用。

为什么一次生成Image可以到处运行,需要先了解Docker:

K8S架构

  • k8s的架构主要是由master节点和node节点构成
  • 一个master节点可以对应多个node节点。

master节点不存储容器

主要由四个部分构成:
api server k8s网关,所有请求指令都必须先到这里
scheduler 调度器,控制网关过来的请求路由到哪个node
controller 控制器,主要用来维护k8s资源对象
etcd 主要用来资源对象

node节点就是存储具体容器的,但是不仅仅只有容器,主要包括:
docker 容器引擎,运行容器的基础环境
kubelet 在每个node节点都存在一份,主要来执行关于资源操作的指令,负责pod的维护。
kube-proxy 代理服务,用于负载均衡,在多个pod之间做负载均衡
fluentd 日志收集服务
pod 是k8s的最小服务单元,pod内部才是容器,k8s通过操作pod来操作容器

pod 也是一个容器,是封装容器的容器,是一个虚拟化的分组,有自己的ip和port。
pod的子容器之间的交互,就像在一台机器上的交互。具体的实现是通过pause容器来实现的。
在初始化一个pod容器的时候,就会生成一个pause容器。这个容器使得pod里面的子容器能够共享网络和存储,方便内部容器之间的调用。

一个Pod中的应用容器共享同一组资源:
PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID;
网络命名空间:Pod中的多个容器能够访问同一个IP和端口范围;
IPC命名空间:Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信;
UTS命名空间:Pod中的多个容器共享一个主机名;
Volumes(共享存储卷):Pod中的各个容器可以访问在Pod级别定义的Volumes;

Node包含的信息:
Node地址:主机的IP地址,或Node ID。
Node的运行状态:Pending、Running、Terminated三种状态。
Node Condition:…
Node系统容量:描述Node可用的系统资源,包括CPU、内存、最大可调度Pod数量等。
其他:内核版本号、Kubernetes版本等。

Pod的生命周期通过Replication Controller来管理;
通过模板进行定义,然后分配到一个Node上运行,在Pod所包含容器运行结束后,Pod结束。

Service可以看作一组提供相同服务的Pod的对外访问接口,Service作用于哪些Pod是通过Label Selector来定义的。

  • 拥有一个指定的名字(比如my-mysql-server);
  • 拥有一个虚拟IP(Cluster IP、Service IP或VIP)和端口号,销毁之前不会改变,只能内网访问;
  • 能够提供某种远程服务能力;
  • 被映射到了提供这种服务能力的一组容器应用上;

Volume是Pod中能够被多个容器访问的共享目录。

Label以key/value的形式附加到各种对象上,如Pod、Service、RC、Node等,以识别这些对象,管理关联关系等,如Service和Pod的关联关系。

RC中定义的Lable筛选出对应的Pod实例,并实时监控其状态和数量,如果实例数量少于定义的副本数量(Replicas),则会根据RC中定义的Pod模板来创建一个新的Pod,然后将此Pod调度到合适的Node上启动运行,直到Pod实例数量达到预定目标。

客户端流程

客户端通过Kubectl命令行工具或Kubectl
Proxy来访问Kubernetes系统,在Kubernetes集群内部的客户端可以直接使用Kuberctl命令管理集群。Kubectl
Proxy是API Server的一个反向代理,在Kubernetes集群外部的客户端可以通过Kubernetes Proxy来访问API
Server。

使用内部流程

通过Kubectl提交一个创建RC的请求,该请求通过API Server被写入etcd中

此时Controller Manager通过API Server的监听资源变化的接口监听到这个RC事件,分析之后,发现当前集群中还没有它所对应的Pod实例,于是根据RC里的Pod模板定义生成一个Pod对象, 通过API Server写入etcd

接下来,此事件被Scheduler发现,它立即执行一个复杂的调度流程,为这个新Pod选定一个落户的Node

通过API Server讲这一结果写入到etcd中,随后,目标Node上运行的Kubelet进程通过API

Server监测到这个“新生的”Pod,并按照它的定义,启动该Pod并任劳任怨地负责它的下半生,直到Pod的生命结束。

随后,我们通过Kubectl提交一个新的映射到该Pod的Service的创建请求,Controller Manager会通过Label标签查询到相关联的Pod实例,然后生成Service的Endpoints信息,并通过API Server写入到etcd中,接下来,所有Node上运行的Proxy进程通过API

Server查询并监听Service对象与其对应的Endpoints信息,建立一个软件方式的负载均衡器来实现Service访问到后端Pod的流量转发功能。

常用命令

Node

[root@master ~]kubectl get no    #查看node节点
[root@master ~]kubectl get no -o wide   #查看node节点
[root@master ~]kubectl describe no   
[root@master ~]kubectl get no -o yaml  #以yaml的格式输出node的详细信息
[root@master ~]kubectl get no -o json	 #以json的格式输出node的详细信息
[root@master ~]kubectl get node --selector=[label_name]   #selector 标签选择器(yaml文件中有)
[root@master ~]kubectl top node [node_name]  #查看node节点各资源的使用情况
[root@master ~]kubectl top node node1

PODS

[root@master ~]kubectl get po 				#pod的信息
[root@master ~]kubectl get po -o wide
[root@master ~]kubectl describe po
[root@master ~]kubectl get po --show-labels      #查看pod对应的标签
[root@master ~]kubectl get po -l app=nginx      	#查看标签为app: nginx 的pod
[root@master ~]kubectl get po -o yaml   				#yaml格式
[root@master ~]kubectl get po -o json					#json格式
[root@master ~]kubectl get pods -- field-selector status.phase=Running   #查看状态为Running的pod

Namespaces

[root@master ~] kubectl get ns   #查看命名空间
[root@master ~] kubectl get ns - o yaml
[root@master ~] kubectl describe ns

Deployments

是用于管理pod的抽象层

kubernetes 微服务注册与发现 kubernetes开发_Pod

[root@master ~] kubectl get deploy
[root@master ~] kubectl describe deploy
[root@master ~] kubectl get deploy - o wide
[root@master ~] kubectl get deploy - o yaml

Service

[root@master ~] kubectl get svc
[root@master ~] kubectl describe svc
[root@master ~] kubectl get svc - o wide
[root@master ~] kubectl get svc - o yaml
[root@master ~] kubectl get svc --show-labels

更多基础命令查看

安装

安装 minikube + kubectl
需要提前安装好Docker,这里就不再赘述了

#kubectl 的安装:
wget https://storage.googleapis.com/kubernetes- release/release/v1.5.1/bin/darwin/amd64/kubectl chmod +x kubectl mv kubectl /usr/local/bin/kubectl 复制代码
#minikube
curl -Lo minikube http://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v0.30.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
复制代码

安装完毕后可以启动k8s环境了,命令行运行 minikube start
minikube ssh 进入minikube的虚拟机内部,执行 docker ps 查看所有的组件容器是否启动成功 如果没有问题退出登录,在外部执行 minikube dashboard 即可在浏览器启动控制台,到这里k8s的实验环境就已经搭建完毕了

部署应用

在k8s只要使用两条指令就可以创建一个集群

一个是kubectl init进行初始化,创建一个master节点

第二条指令就是kubectl join xxx创建一个node节点,加入这个集群

kubernetes 微服务注册与发现 kubernetes开发_Server_02

kubectl 来创建一个deployment:
第一步就是创建 Deployment ,它将负责创建和更新我们的应用实例,并且持续监控应用的状态。

kubectl run <node_name>--image=<url> --port=8080
  • 执行后master节点将会选择一个合适的node来部署该应用(minikube环境下只有一个node),创建完成后可以使用 kubectl get deployment 来查看该应用:
# 开启代理
kubectl proxy
#可以先用 kubectl get pod 来查看pod名
  • 代理启动后在新终端通过restful api的方式就可以通过代理访问到内部pod所提供的服务,restful的url模式如下:
    /api/v1/namespace/{namespace}/pods/{name}/proxy/{path:*}

kubernetes 微服务注册与发现 kubernetes开发_kubernetes 微服务注册与发现_03

Service

当我们需要对外提供可用的真实服务时,需要更加可靠的手段,那就是 Service

kubernetes 微服务注册与发现 kubernetes开发_kubernetes 微服务注册与发现_04

  • 一个Service可以映射多个Pod,为了把多个Pod在逻辑上组合起来,k8s又引入了 Label的概念,简单的说就是每个Pod上都可以打一个Label(标签),具有相同Label的Pod就成为一个逻辑分组。Service就是通过Label Selector的方式来关联多个Pod的
  • 创建一个Service并将它暴露到外部,通常可以有 LoadBalancer 和 NodePort
    两种手段,不过minikube只支持后者,使用 kubectl expose 命令即可创建Service:
  • 使用 kubectl get service 我们可以看到已经创建的服务,其中 kubernetes 是k8s默认已经创建好的。可以看到,新创建的service把对应pod的8080端口暴露到了外部的32344端口,接下来通过这个端口就可以访问到hello world服务了:

kubernetes 微服务注册与发现 kubernetes开发_Server_05

  • 这里的 IP 是minikube的docker-daemon的ip,可以通过 minikube docker-env 来查看

kubernetes 微服务注册与发现 kubernetes开发_Pod_06

  • 我们可以查看一下service和pod的详情,来看看Label是否按照我们预期的被创建:

kubernetes 微服务注册与发现 kubernetes开发_kubernetes 微服务注册与发现_07


label是 key=value 的形式被创建的,如果想要自定义一些label,使用 kubectl label 命令即可:

kubernetes 微服务注册与发现 kubernetes开发_kubernetes 微服务注册与发现_08

  • 在pod和service非常多的时候,可以用作一种过滤的手段,使用-l参数即可进行筛选,就像sql的where语句一样:

kubernetes 微服务注册与发现 kubernetes开发_Server_09

  • 最后,如果想要删除一个service,只需要运行 kubectl delete service [服务名]
    即可,当然服务删除后pod仍然存在并且会持续运行,只是对外的入口消失了而已。