学习K8s:从 Deployment 到 Service

K8s,Kubernetes 的缩写,起源于希腊语意为舵手、领航员。是一种容器编排工具,于14.7被Docker收购,同类产品有docker swarm:

学习K8s:从 Deployment 到 Service_第1张图片

学习K8s:从 Deployment 到 Service_第2张图片

 

 

k8s master 节点:

master节点:k8s集群的管理节点,提供集群资源数据访问入口,负责运行Api Server进程、Scheduler服务进程、Controller Manager服务进程、etcd存储服务,负责关联工作节点 Node。

学习K8s:从 Deployment 到 Service_第3张图片

 

k8s node 节点:

node节点:k8s集群中运行Pod的服务节点,是k8s集群最小操作单元,用于承载被分配Pod的运行(Pod宿主机); 关联Master管理节点,拥有名称、IP、系统资源信息; 负责运行:docker eninge服务、守护进程kunelet、负载均衡器kube-proxy;

学习K8s:从 Deployment 到 Service_第4张图片

 

每个Node节点都运行一组关键进程: Docker Engine:负责本机容器的创建和管理工作; kubelet:负责对 Pod对应的容器的创建、启停等任务;(Node节点可以在运行时动态增加到K8s集群中) kube-proxy:实现K8s Service的通信与负载均衡机制的重要组件;

K8s【推荐的、默认的】Node管理方式:kubelet会向master注册自己,kubelet进程会定时向Master汇报自身情报(如操作系统、Docker版本、CPU和内存,以及有哪些Pod在运行等等),这样Master可以获知每个Node节点的资源使用情况,并实现高效均衡的资源调度策略。

 

Pod:是k8s最小的调度单位,包含一/多个container,内部共享一个namespace。

 

什么是控制器?

K8s 中内建了很多 Controller 控制器,这些相当于一个状态机,用来控制 Pod 的具体状态和行为。

ReplicationController 和 ReplicaSet Deployment(RC、RS)
Deployment
DaemonSet
StateFulSet
Job/CronJob
Horizontal Pod Autoscaling

ReplicationController 和 ReplicaSet:

ReplicationController(RC)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收;在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController 。ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector;

 

RS/RC 与 Deployment 的关联

apiVersion: extensions/v1beta1 
kind: ReplicaSet
metadata:
    name: frontend
spec:
    replicas: 3
    selector:
        matchLabels:
            tier: frontend
    template:
        metadata: 
            labels:
                tier: frontend
        spec:
            containers:
            -  name: php-redis
                image:  nginx:1.7.9 
                env:
                - name: GET_HOSTS_FROM
                    value: dns
                ports:
                -  containerPort: 80

RS 与 Deployment 的关联

学习K8s:从 Deployment 到 Service_第5张图片

 

Deployment:

Deployment,是常见的K8s对象类型,提供了对 Pod 和 ReplicaSet 的声明式定义 (declarative) 方法和管理方式,每个Deployment对应集群的一次部署,常用来创建 ReplicaSet 和 Pod,解决了 ReplicaSet 更新的诸多问题,用来替代以前的ReplicationController来方便的管理应用。(部署一个新的微服务往往不会直接在集群中使用 ReplicaSet,因为ReplicaSet功能不够强大,不支持一些常见的更新、扩容、缩容运维操作,引入 Deployment 就是为了支持这些复杂操作。)

在 K8s 集群中创建 Deployment 对象时,会创建 Deployment 资源、ReplicaSet、三个Pod对象,组成以下的拓扑结构:

学习K8s:从 Deployment 到 Service_第6张图片

 

拓扑结构中的子节点都是稳定的,任意节点删除都会被 K8s 控制器重启。

每个 Deployment 都会和它的依赖组成以下的拓扑结构,在这个拓扑结构中的子节点都是『稳定』的,任意节点的删除都会被 Kubernetes 的控制器重启。

DeploymentController:负责管理 K8s 集群中的所有 Deployment 对象,实现 Deployment 对象的各种操作:同步、扩容、重新创建、滚动更新、回滚、暂定恢复、删除。

Deployment:典型的应用场景包括: ​ ·定义 Deployment 来创建 Pod 和 ReplicaSet; ​ ·滚动升级和回滚应用 ​ ·扩容和缩容; ​ ·暂停和继续 Deployment;

 

1.部署一个简单的 Nginx 应用

apiVersion: extensions/v1beta1 
kind: Deployment
metadata:
    name: nginx-deployment
spec:
    replicas: 3
    template:
        metadata: 
            labels:
                app: nginx
        spec:
            containers:
            -  name: nginx
                image:  nginx:1.7.9 
                ports:
                -  containerPort: 80
kubectl  create  -f  https://kubernetes.io/docs/user-guide/nginx-deployment.yaml  --record
## --record 参数可以记录命令,我们可以很方便的查看每次revision的变化

2.扩容

kubectl  scale  deployment  nginx-deployment  --replicas  10

3.为 Deployment 设置自动扩展

## (若集群支持 horizontal pod autoscaling)
kubectl  autoscale  deployment  nginx-deployment  --min=10  --max=15  --cpu-percent=80

4.更新镜像

kubectl  set  image  deployment/nginx-deployment  nginx=nginx:1.9.1

5.回滚

kubectl  rollout  undo  deployment/nginx-deployment

 

​集群service管理包括:

  • 网络代理模式
  • 服务代理
  • 服务发现
  • 发布服务

概述


​Service 是对一组提供相同功能的 Pods 的抽象,并为它们提供一个统一的入口。

借助 Service,应用可以方便的实现服务发现与负载均衡,并实现应用的零宕机升级。

Service 通过标签来选取服务后端,一般配合 Replication Controller 或者 Deployment 来保证后端容器的正常运行。这些匹配标签的 Pod IP 和端口列表组成 endpoints,由 kube-proxy 负责将服务 IP 负载均衡到这些 endpoints 上。

Service 有四种类型:

  • ClusterIP:默认类型,自动分配一个仅 cluster 内部可以访问的虚拟 IP
  • NodePort:在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 NodeIP:NodePort 来访问该服务。如果 kube-proxy 设置了 –nodeport-addresses=10.240.0.0/16(v1.10 支持),那么仅该 NodePort 仅对设置在范围内的 IP 有效。
  • LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 :NodePort
  • ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)。需要 kube-dns 版本在 1.7 以上。

​​

另外,也可以将已有的服务以 Service 的形式加入到 Kubernetes 集群中来,只需要在创建 Service 的时候不指定 Label selector,而是在 Service 创建好后手动为其添加 endpoint。

K8s 的 Service

K8s 中的 Pod 是有生命周期的对象,随时都有可能由于集群的状态变化而被销毁和创建,此时要面临的问题:当一些 Pod 需要为其它 Pod 提供服务时,如何提供同一功能服务的一组 Pod 建立一个抽象并追踪这组服务中节点的健康状态。 ​ 这个抽象在 K8s 集群中就是 Service,每个K8s的 Service 都是一组Pod的逻辑集合和访问方式的抽象,可以把 Service 加上的一组 Pod 称为一个微服务。

K8s Service 定义了这样一个抽象:一个Pod的逻辑分组,一种够可以访问它们的策略 - - 通常称为微服务。 这一组Pod能够被Service访问到,通常是通过Label Selector。

学习K8s:从 Deployment 到 Service_第7张图片

K8s 中 Service 实现原理: 1.如何处理服务的创建;2.如何转发来自节点内部和外部的流量;

创建服务:

在 K8s 中创建一个新的 Service 对象需要两大模块同时协作:控制器 与 kube-proxy。 控制器,需要在每次客户端创建新的 Service 对象时生成其他用于暴露一组 Pod 的 K8s 对象,即 Endpoint 对象; kube-proxy,运行在 K8s 集群中的每一个节点上,会根据 Service 和 Endpoint 的变动改变节点上 iptables 或 ipvs 中保存的规则。

ServiceController 在 Service 对象变动时发生了什么事情:

学习K8s:从 Deployment 到 Service_第8张图片

 

 

网络代理模式


拥有三种代理模式:userspace、iptables和ipvs。

现在默认使用iptables,在1.8版本之后增加了ipvs功能。

早期代理的方式

学习K8s:从 Deployment 到 Service_第9张图片

 

client先请求serviceip,经由iptables转发到kube-proxy上之后再转发到pod上去。这种方式效率比较低。

当前iptables代理方式

学习K8s:从 Deployment 到 Service_第10张图片

 

​client请求serviceip后会直接转发到pod上。这种模式性能会高很多。kube-proxy就会负责将pod地址生成在node节点iptables规则中。

ipvs代理方式

这种方式是通过内核模块ipvs实现转发,这种效率更高。

服务代理


​​

创建yaml配置文件

创建一个service.yaml文件:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443

selector字段中指定了为哪一个标签的app进行负载均衡。ports字段指定了暴露的端口,每一个- name指定一组端口,targetPort为目标容器的端口。

创建service

kubectl create -f service.yaml

查看service

然后通过命令kubectl get svc查看创建的service

 

通过命令kubectl get endpoints my-service查看创建的service当后端代理的pod的ip 

 

并没有给它分配pod所以代理的ip为空。

配置service代理pod

首先查看了一下当前有哪些pod: 

 

现在想让刚创建的service代理nginx-pod

​​修改service.yaml文件中app:MyAppapp:nginx,这样就可以匹配到标签为app=nginx的pod了。

然后重新生效这个service:

kubectl replace -f service.yaml --force

 

pod已经连接上了。

通过clusterip访问pod

首先查看下service的clusterip: 

 

然后在节点上可以通过这个ip和端口的方式访问pod上的应用: 

学习K8s:从 Deployment 到 Service_第11张图片

 

service服务发现


服务发现支持Service环境变量和DNS两种模式

环境变量

当一个pod运行到node,kubelet会为每个容器添加一组环境变量,Pod容器中程序就可以使用这些环境变量发现Service。

环境变量名格式如下:

{SVCNAME}_SERVICE_HOST
{SVCNAME}_SERVICE_PORT

 

其中服务名和端口名转为大写,连字符转换为下划线。查看方法是进入pod中输入env查看环境变量,在程序中调用这个变量就可以访问这个组件。

​​限制: 
1)Pod和Service的创建顺序是有要求的,Service必须在Pod创建之前被创建,否则环境变量不会设置到Pod中。 
2)Pod只能获取同Namespace中的Service环境变量。

​​

DNS

DNS服务监视Kubernetes API,为每一个Service创建DNS记录用于域名解析。这样Pod中就可以通过DNS域名获取Service的访问地址。

工作原理

学习K8s:从 Deployment 到 Service_第12张图片

 

kube-dns用于记录集群svc的域名解析相关记录,dnsmasq主要用于dns缓存。

yaml文件中为kube-dns指定了一个固定的ip,所以需要注意修改node节点kubelet配置的kube-dns是否为这个ip(我之前配置的不是,所以要修改)

 

集群应用发布


服务类型

ClusterIP: 
分配一个内部集群IP地址,只能在集群内部访问(同Namespace内的Pod),默认ServiceType。

NodePort: 
分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务,可以在集群外部访问。 
访问地址::

LoadBalancer: 
分配一个内部集群IP地址,并在每个节点上启用一个端口来暴露服务。 
除此之外,Kubernetes会请求底层云平台上的负载均衡器,将每个Node([NodeIP]:[NodePort])作为后端添加进去。 

学习K8s:从 Deployment 到 Service_第13张图片

 

学习K8s:从 Deployment 到 Service_第14张图片

 

 

 

你可能感兴趣的:(云计算,系统与软件,Docker,K8s,容器技术)