Kubernetes集群之部署

目录

一、k8s的简介

1.背景介绍. 5

2.什么是kubernetes 5

3 Kubernetes的核心概念. 7

3.1.Master 7

3.2.Node 7

3.3.Pod 7

3.4.Replication Controller 8

3.5.Service 8

3.6.Label 8

4 Kubernetes架构和组件. 9

4.1Kubernetes 组件: 9

4.2 Kubernetes Node运行节点,运行管理业务容器,包含如下组件: 11

二、基于kubernetes构建Docker集群环境实战. 12

1 .etcd: 12

2.flannel: 12

3.kube-apiserver: 12

4.kube-controller-manager: 12

5.kube-scheduler 13

6.kubelet 13

7.kube-proxy 13

三、准备环境. 13

1.、架构拓扑图:. 14

2、环境规划centos7系统机器两台:. 14

3、环境说明:. 15

四、部署集群. 16

1 下载二进制包. 16

2 下载完成后,上传到服务器:. 17

五、关闭系统运行的防火墙及selinux和设置时区主机名. 17

1.如果系统开启了防火墙则按如下步骤关闭防火墙(所有机器). 18

2.关闭selinux 18

3.分别设置主机名为master1 node1 ... 时区. 18

六、master(即kubernetes-server)主机机器安装配置. 18

1.安装etcd 18

1.1 解压文件. 18

1.2 复制文件到指定目录或就在当前目录,但需bin目录下. 18

1.3配置etcd的配置文件. 19

1.4 配置systemctl管理. 19

1.5 配置好后。执行以下命令. 20

1.6 查看etcd状态. 20

1.7 验证是否往etcd中写数据是否成功,执行. 21

2.安装kubernetes(即kubernetes-server) 21

2.1 解压kubernetes-server-linux-amd64.tar.gz 文件. 21

2.2 拷贝kube-apiserver文件. 22

2.3 在/data/telecom/k8s/kubernetes下创建apiserver配置文件  22

2.4 配置systemctl管理即建立kube-apiserver.service文件. 23

2.5 配置好后,执行以下命令:. 24

2.6查看kube-apiserver.service状态. 24

2.7 配置kube-scheduler配置文件. 25

2.8 配置systemd服务文件kube-scheduler.service 25

2.9 配置好后,启动服务,并设置开机启动. 26

2.10 创建kube-controller-manager配置文件. 26

2.11 配置systemd服务文件kube-controller-manager.service 26

2.12 启动服务,并设置开机启动. 27

3.kubernetes-server配置完成小结. 27

3.1 查看Master节点组件进程状态. 28

3.2 如果启动失败,请查看启动日志. 28

七、node(即kubernetes-node)节点主机服务器的安装和配置. 28

1 . node节点的介绍. 28

2.解压node节点文件. 28

3.进入解压的目录kubernetes 29

4.默认或移动kubelet文件位置. 29

5.创建连接master apiserver的kubelet配置文件,即kubelet.yaml 29

6.创建kubelet配置文件. 30

7.配置systemd下的服务文件管理,即kubelet.service文件. 31

8.创建kube-proxy配置文件. 32

9.配置systemd下的服务管理kube-proxy.service 33

10. 配置完成后启动服务,并设置开机启动. 34

11. 查看Node节点组件进程状态. 34

12 如果启动失败,请查看启动日志. 34

13. 验证集群是否部署成功. 35

14.在master机器上查看集群节点状态. 35

15 .node节点的小结. 35

八、设置网络(待修改中) 35

1.设置etcd网络. 35

2.安装flannel 36

3. 准备启动服务. 36

4.配置flannel网络. 36

九、Kubernetes之深入了解Pod及yaml脚本. 36

1、yaml格式的Pod配置文件内容及注解. 36

2、Pod基本用法:. 38

3、静态Pod 40

4、Pod容器共享Volume 41

5.Pod的配置管理. 42

5.1 ConfigMap:容器应用的配置管理. 42

5.2 ConfigMap的创建. 42

5.3使用ConfigMap的条件限制. 44

6.Pod生命周期和重启策略. 44

7、Pod健康检查. 45

7.1 ExecAction 45

7.2 TCPSocketAction 46

7.3 HTTPGetAction 46

8.玩转Pod调度. 47

8.1 RC、Deployment:全自动调度. 47

8.2 DaemonSet:特定场景调度. 48

8.3 批处理调度. 49

9.Pod的扩容和缩荣. 49

10.Pod的滚动升级. 49

一、Kubernetes系列之介绍篇

1.背景介绍

  云计算飞速发展

    - IaaS

    - PaaS

    - SaaS

  Docker技术突飞猛进

    - 一次构建,到处运行

    - 容器的快速轻量

    - 完整的生态环境

2.什么是kubernetes

  首先,他是一个全新的基于容器技术的分布式架构领先方案。Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg)。在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能,提了大规模容器集群管理的便捷性。

  Kubernetes是一个完备的分布式系统支撑平台,具有完备的集群管理能力,多扩多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和发现机制、內建智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制以及多粒度的资源配额管理能力。同时Kubernetes提供完善的管理工具,涵盖了包括开发、部署测试、运维监控在内的各个环节。

Kubernetes中,Service是分布式集群架构的核心,一个Service对象拥有如下关键特征:

拥有一个唯一指定的名字

拥有一个虚拟IP(Cluster IP、Service IP、或VIP)和端口号

能够体统某种远程服务能力

被映射到了提供这种服务能力的一组容器应用上

  Service的服务进程目前都是基于Socket通信方式对外提供服务,比如Redis、Memcache、MySQL、Web Server,或者是实现了某个具体业务的一个特定的TCP Server进程,虽然一个Service通常由多个相关的服务进程来提供服务,每个服务进程都有一个独立的Endpoint(IP+Port)访问点,但Kubernetes能够让我们通过服务连接到指定的Service上。有了Kubernetes内奸的透明负载均衡和故障恢复机制,不管后端有多少服务进程,也不管某个服务进程是否会由于发生故障而重新部署到其他机器,都不会影响我们队服务的正常调用,更重要的是这个Service本身一旦创建就不会发生变化,意味着在Kubernetes集群中,我们不用为了服务的IP地址的变化问题而头疼了。

  容器提供了强大的隔离功能,所有有必要把为Service提供服务的这组进程放入容器中进行隔离。为此,Kubernetes设计了Pod对象,将每个服务进程包装到相对应的Pod中,使其成为Pod中运行的一个容器。为了建立Service与Pod间的关联管理,Kubernetes给每个Pod贴上一个标签Label,比如运行MySQL的Pod贴上name=mysql标签,给运行PHP的Pod贴上name=php标签,然后给相应的Service定义标签选择器Label Selector,这样就能巧妙的解决了Service于Pod的关联问题。

  在集群管理方面,Kubernetes将集群中的机器划分为一个Master节点和一群工作节点Node,其中,在Master节点运行着集群管理相关的一组进程kube-apiserver、kube-controller-manager和kube-scheduler,这些进程实现了整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理能力,并且都是全自动完成的。Node作为集群中的工作节点,运行真正的应用程序,在Node上Kubernetes管理的最小运行单元是Pod。Node上运行着Kubernetes的kubelet、kube-proxy服务进程,这些服务进程负责Pod的创建、启动、监控、重启、销毁以及实现软件模式的负载均衡器。

  在Kubernetes集群中,它解决了传统IT系统中服务扩容和升级的两大难题。你只需为需要扩容的Service关联的Pod创建一个Replication Controller简称(RC),则该Service的扩容及后续的升级等问题将迎刃而解。在一个RC定义文件中包括以下3个关键信息。

目标Pod的定义

目标Pod需要运行的副本数量(Replicas)

要监控的目标Pod标签(Label)

  在创建好RC后,Kubernetes会通过RC中定义的的Label筛选出对应Pod实例并实时监控其状态和数量,如果实例数量少于定义的副本数量,则会根据RC中定义的Pod模板来创建一个新的Pod,然后将新Pod调度到合适的Node上启动运行,知道Pod实例的数量达到预定目标,这个过程完全是自动化。

  

 Kubernetes优势:

    - 容器编排

    - 轻量级

    - 开源

    - 弹性伸缩

    - 负载均衡

3 Kubernetes的核心概念

3.1.Master

  k8s集群的管理节点,负责管理集群,提供集群的资源数据访问入口。拥有Etcd存储服务(可选),运行Api Server进程,Controller Manager服务进程及Scheduler服务进程,关联工作节点Node。Kubernetes API server提供HTTP Rest接口的关键服务进程,是Kubernetes里所有资源的增、删、改、查等操作的唯一入口。也是集群控制的入口进程;Kubernetes Controller Manager是Kubernetes所有资源对象的自动化控制中心;Kubernetes Schedule是负责资源调度(Pod调度)的进程

3.2.Node

  Node是Kubernetes集群架构中运行Pod的服务节点(亦叫agent或minion)。Node是Kubernetes集群操作的单元,用来承载被分配Pod的运行,是Pod运行的宿主机。关联Master管理节点,拥有名称和IP、系统资源信息。运行docker eninge服务,守护进程kunelet及负载均衡器kube-proxy.

每个Node节点都运行着以下一组关键进程

kubelet:负责对Pod对于的容器的创建、启停等任务

kube-proxy:实现Kubernetes Service的通信与负载均衡机制的重要组件

Docker Engine(Docker):Docker引擎,负责本机容器的创建和管理工作

  Node节点可以在运行期间动态增加到Kubernetes集群中,默认情况下,kubelet会想master注册自己,这也是Kubernetes推荐的Node管理方式,kubelet进程会定时向Master汇报自身情报,如操作系统、Docker版本、CPU和内存,以及有哪些Pod在运行等等,这样Master可以获知每个Node节点的资源使用情况,冰实现高效均衡的资源调度策略。、

3.3.Pod

  运行于Node节点上,若干相关容器的组合。Pod内包含的容器运行在同一宿主机上,使用相同的网络命名空间、IP地址和端口,能够通过localhost进行通。Pod是Kurbernetes进行创建、调度和管理的最小单位,它提供了比容器更高层次的抽象,使得部署和管理更加灵活。一个Pod可以包含一个容器或者多个相关容器。

  Pod其实有两种类型:普通Pod和静态Pod,后者比较特殊,它并不存在Kubernetes的etcd存储中,而是存放在某个具体的Node上的一个具体文件中,并且只在此Node上启动。普通Pod一旦被创建,就会被放入etcd存储中,随后会被Kubernetes Master调度到摸个具体的Node上进行绑定,随后该Pod被对应的Node上的kubelet进程实例化成一组相关的Docker容器冰启动起来,在。在默认情况下,当Pod里的某个容器停止时,Kubernetes会自动检测到这个问起并且重启这个Pod(重启Pod里的所有容器),如果Pod所在的Node宕机,则会将这个Node上的所有Pod重新调度到其他节点上。

3.4.Replication Controller

  Replication Controller用来管理Pod的副本,保证集群中存在指定数量的Pod副本。集群中副本的数量大于指定数量,则会停止指定数量之外的多余容器数量,反之,则会启动少于指定数量个数的容器,保证数量不变。Replication Controller是实现弹性伸缩、动态扩容和滚动升级的核心。

3.5.Service

  Service定义了Pod的逻辑集合和访问该集合的策略,是真实服务的抽象。Service提供了一个统一的服务访问入口以及服务代理和发现机制,关联多个相同Label的Pod,用户不需要了解后台Pod是如何运行。

外部系统访问Service的问题

  首先需要弄明白Kubernetes的三种IP这个问题

    Node IP:Node节点的IP地址

    Pod IP: Pod的IP地址

    Cluster IP:Service的IP地址

  首先,Node IP是Kubernetes集群中节点的物理网卡IP地址,所有属于这个网络的服务器之间都能通过这个网络直接通信。这也表明Kubernetes集群之外的节点访问Kubernetes集群之内的某个节点或者TCP/IP服务的时候,必须通过Node IP进行通信

  其次,Pod IP是每个Pod的IP地址,他是Docker Engine根据docker0网桥的IP地址段进行分配的,通常是一个虚拟的二层网络。

  最后Cluster IP是一个虚拟的IP,但更像是一个伪造的IP网络,原因有以下几点

Cluster IP仅仅作用于Kubernetes Service这个对象,并由Kubernetes管理和分配P地址

Cluster IP无法被ping,他没有一个“实体网络对象”来响应

Cluster IP只能结合Service Port组成一个具体的通信端口,单独的Cluster IP不具备通信的基础,并且他们属于Kubernetes集群这样一个封闭的空间。

Kubernetes集群之内,Node IP网、Pod IP网于Cluster IP网之间的通信,采用的是Kubernetes自己设计的一种编程方式的特殊路由规则。

3.6.Label

 Kubernetes中的任意API对象都是通过Label进行标识,Label的实质是一系列的Key/Value键值对,其中key于value由用户自己指定。Label可以附加在各种资源对象上,如Node、Pod、Service、RC等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去。Label是Replication Controller和Service运行的基础,二者通过Label来进行关联Node上运行的Pod。

我们可以通过给指定的资源对象捆绑一个或者多个不同的Label来实现多维度的资源分组管理功能,以便于灵活、方便的进行资源分配、调度、配置等管理工作。

一些常用的Label如下:

版本标签:"release":"stable","release":"canary"......

环境标签:"environment":"dev","environment":"qa","environment":"production"

架构标签:"tier":"frontend","tier":"backend","tier":"middleware"

分区标签:"partition":"customerA","partition":"customerB"

质量管控标签:"track":"daily","track":"weekly"

  Label相当于我们熟悉的标签,给某个资源对象定义一个Label就相当于给它大了一个标签,随后可以通过Label Selector(标签选择器)查询和筛选拥有某些Label的资源对象,Kubernetes通过这种方式实现了类似SQL的简单又通用的对象查询机制。

  Label Selector在Kubernetes中重要使用场景如下:

  kube-Controller进程通过资源对象RC上定义Label Selector来筛选要监控的Pod副本的数量,从而实现副本数量始终符合预期设定的全自动控制流程

  kube-proxy进程通过Service的Label Selector来选择对应的Pod,自动建立起每个Service岛对应Pod的请求转发路由表,从而实现Service的智能负载均衡

  通过对某些Node定义特定的Label,并且在Pod定义文件中使用Nodeselector这种标签调度策略,kuber-scheduler进程可以实现Pod”定向调度“的特性

4 Kubernetes架构和组件

  - 服务分组,小集群,多集群

  - 服务分组,大集群,单集群

4.1Kubernetes 组件:

  Kubernetes Master控制组件,调度管理整个系统(集群),包含如下组件:

  4.1.1.Kubernetes API Server

    作为Kubernetes系统的入口,其封装了核心对象的增删改查操作,以RESTful API接口方式提供给外部客户和内部组件调用。维护的REST对象持久化到Etcd中存储。

  4.1.2.Kubernetes Scheduler

    为新建立的Pod进行节点(node)选择(即分配机器),负责集群的资源调度。组件抽离,可以方便替换成其他调度器。

  4.1.3.Kubernetes Controller

    负责执行各种控制器,目前已经提供了很多控制器来保证Kubernetes的正常运行。

  4.1.4. Replication Controller

    管理维护Replication Controller,关联Replication Controller和Pod,保证Replication Controller定义的副本数量与实际运行Pod数量一致。

  4.1.5. Node Controller

    管理维护Node,定期检查Node的健康状态,标识出(失效|未失效)的Node节点。

  4.1.6. Namespace Controller

    管理维护Namespace,定期清理无效的Namespace,包括Namesapce下的API对象,比如Pod、Service等。

  4.1.7. Service Controller

    管理维护Service,提供负载以及服务代理。

  4.1.8.EndPoints Controller

    管理维护Endpoints,关联Service和Pod,创建Endpoints为Service的后端,当Pod发生变化时,实时更新Endpoints。

  4.1.9. Service Account Controller

    管理维护Service Account,为每个Namespace创建默认的Service Account,同时为Service Account创建Service Account Secret。

  4.1.10. Persistent Volume Controller

    管理维护Persistent Volume和Persistent Volume Claim,为新的Persistent Volume Claim分配Persistent Volume进行绑定,为释放的Persistent Volume执行清理回收。

  4.1.11. Daemon Set Controller

    管理维护Daemon Set,负责创建Daemon Pod,保证指定的Node上正常的运行Daemon Pod。

  4.1.12. Deployment Controller

    管理维护Deployment,关联Deployment和Replication Controller,保证运行指定数量的Pod。当Deployment更新时,控制实现Replication Controller和 Pod的更新。

  4.1.13.Job Controller

    管理维护Job,为Jod创建一次性任务Pod,保证完成Job指定完成的任务数目

  4.1.14. Pod Autoscaler Controller

    实现Pod的自动伸缩,定时获取监控数据,进行策略匹配,当满足条件时执行Pod的伸缩动作。

4.2 Kubernetes Node运行节点,运行管理业务容器,包含如下组件:

  4.2.1.Kubelet

    负责管控容器,Kubelet会从Kubernetes API Server接收Pod的创建请求,启动和停止容器,监控容器运行状态并汇报给Kubernetes API Server。

  4.2.2.Kubernetes Proxy

    负责为Pod创建代理服务,Kubernetes Proxy会从Kubernetes API Server获取所有的Service信息,并根据Service的信息创建代理服务,实现Service到Pod的请求路由和转发,从而实现Kubernetes层级的虚拟转发网络。

  4.2.3.Docker

    Node上需要运行容器服务

二、基于kubernetes构建Docker集群环境实战

kubernetes是google公司基于docker所做的一个分布式集群,有以下主件组成

1 .etcd:

高可用存储共享配置和服务发现,作为与node机器上的flannel配套使用,作用是使每台 node上运行的docker拥有不同的ip段,最终目的是使不同的node上正在运行的docker containner都有一个与别的任意一个containner(别的node上运行的docker containner)不一样的IP地址。

2.flannel:

网络结构支持

3.kube-apiserver:

不论通过kubectl还是使用remote api 直接控制,都要经过apiserver

4.kube-controller-manager: 

对replication controller, endpoints controller, namespace controller, and serviceaccounts controller的循环控制,与kube-apiserver交互,保证这些controller工作

5.kube-scheduler

Kubernetes scheduler的作用就是根据特定的调度算法将pod调度到指定的工作节点(node)上,这一过程也叫绑定(bind)

6.kubelet

Kubelet运行在Kubernetes Node上. 它是container agent的逻辑继任者

7.kube-proxy

kube-proxy是kubernetes 里运行在node节点上的一个组件, 它起的作用是一个服务代理的角色

图为GIT+Jenkins+Kubernetes+Docker+Etcd+confd+Nginx+Glusterfs架构:

如下:

三、准备环境

1.、架构拓扑图:

2、环境规划centos7系统机器两台:

132.121.117.242: 用来安装kubernetes master

132.121.117.241: 用作kubernetes node (node1)

角色

IP

组件

master

122.111.110.119

etcd

kube-apiserver

kube-controller-manager

kube-scheduler

node01

122.111.110.120

kubelet

kube-proxy

docker

node02

122.111.110.121

kubelet

kube-proxy

docker

3、环境说明:

操作系统: CentOS7

Kubernetes版本:v1.8.3

Docker版本:v17.09-ce

均采用当前最新稳定版本。

关闭selinux。

备注:本人用的版本为以下:

查看系统内核:uname -r   显示结果3.10.0-229.el7.x86_64

查看系统版本:cat /etc/centos-release

显示结果 CentOS Linux release 7.1.1503 (Core)

查看系统位数:getconf LONG_BIT

操作系统: CentOS Linux release 7.1.1503 (Core)

Kubernetes版本:v1.10.

Docker版本:v17.05-ce

Etcd版本:v3.34

关闭selinux。

部署部分

四、部署集群

1 下载二进制包

Kubernetes软件包及ETCD

可以到官方的下载地址下载,地址是:点击打开链接,最新下载版本是V1.10,会被墙,可以参考点击打开链接,无论如何我还是把V1.0的client binary、server binary、node binary下载下来了。ETCD可以到点击打开链接下载。

软件包   用途

kubernetes-server-linux-amd64.tar.gz

版本是V1.10,包含KUBE-APISERVER,KUBE-CONTROLLER-MANAGER,KUBE-SCHEDULE

下载地址: https://pan.baidu.com/s/13wm4-ekgWv2BWsCRnY38oQ

kubernetes-node-linux-amd64.tar.gz

版本是V1.10,   包含KUBELET,KUBE-PROXY,KUBECTL,需要先安装Docker

下载地址:https://pan.baidu.com/s/18PsRGxFIwqVbRIMRqZ8fgA

etcd-v3.3.4-linux-amd64.tar.gz

版本是V3.34,Kubernetes Master需要ETCD数据存储

下载地址:https://pan.baidu.com/s/1jy7DN7z6TUWNWGjBoN92cw

Docker

版本V1.17.05

或打开下面网址,下载下面两个红色框框的包。

https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.8.md#v183

2 下载完成后,上传到服务器:

kubernetes-server-linux-amd64.tar.gz上传到master节点。

kubernetes-node-linux-amd64.tar.gz 上传到node节点。

etcd-v3.3.4-linux-amd64.tar.gz上传到node节点

五、关闭系统运行的防火墙及selinux和设置时区主机名

1.如果系统开启了防火墙则按如下步骤关闭防火墙(所有机器)

# systemctl stop firewalld # systemctl disable firewalld

2.关闭selinux

1

2

#setenforce 0

#sed -i '/^SELINUX=/cSELINUX=disabled' /etc/sysconfig/selinux

3.分别设置主机名为master1 node1 ... 时区

设置时区,master、node机器都需执行,时间统一

timedatectl set-timezone Asia/Shanghai

设置master主机名

hostnamectl set-hostname master

设置node主机名

hostnamectl set-hostname node    #node执行

六、master(即kubernetes-server)主机机器安装配置

1.安装etcd

ETCD是用于共享配置和服务发现的分布式、一致性的KV存储系统,主要包括了增删改查、安全认证、集群、选举、事务、分布式锁、Watch机制等等,实现了RAFT协议,功能相当强大,coreos出品

l1.1 解压文件

etcd-v3.3.4-linux-amd64.tar.gz

1.2 复制文件到指定目录或就在当前目录,但需bin目录下

把解压目录下的etcd和etcdctl复制到/usr/local/bin目下 ,或自己建一个bin目录,然后把etcd和etcdctl放在建的bin目录下

切换到/usr/local/bin/下

1.3配置etcd的配置文件

确保列出的这些项都配置正确并且没有被注释掉,下面的配置都是如此 

[telecom@master ~]$ vim /etc/etcd/etcd.conf

ETCD_NAME="default"

ETCD_DATA_DIR="/data/telecom/k8s/etcd1/data/default.etcd"

ETCD_LISTEN_PEER_URLS="http:// :2380"

ETCD_LISTEN_CLIENT_URLS="http://127.0.0.1:2379,http://127.0.0.1:2379,http://122.111.110.119:2379,http://122.111.110.119:4001"

ETCD_INITIAL_ADVERTISE_PEER_URLS="http://122.111.110.119:2380"

# if you use different ETCD_NAME (e.g. test), set ETCD_INITIAL_CLUSTER value for this name, i.e. "test=http://..."

ETCD_INITIAL_CLUSTER="default=http://122.111.110.119:2380"

ETCD_INITIAL_CLUSTER_STATE="new"

ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"

ETCD_HEARTBEAT_INTERVAL=6000

ETCD_ELECTION_TIMEOUT=30000

1.4 配置systemctl管理

在/etc/systemd/system/目录下创建etcd.service,如果没有system这个目录,则创建就可以,首先创建ETCD的存储的目录地址/home/chen/etcd/data,然后创建ETCD的配置文件目录/etc/etcd/,因为我们用的ETCD默认配置,所以/etc/etcd/etcd.conf空文件即可。

[telecom@master ~]$ vim /etc/systemd/system/etcd.service

[Unit]

Description=etcd server

After=network.target

After=network-online.target

Wants=network-online.target

[Service]

#Type=simple

Type=notify

WorkingDirectory=/data/telecom/k8s/etcd1/data/default.etcd

EnvironmentFile=-/etc/etcd/etcd.conf

ExecStart=/usr/local/bin/etcd

[Install]

WantedBy=multi-user.target

1.5 配置好后。执行以下命令

systemctl daemon-reload   

systemctl enable etcd.service

systemctl start etcd.service

systemctl status etcd.service

systemctl stop etcd.service

1.6 查看etcd状态

1.7 验证是否往etcd中写数据是否成功,执行

  export ETCDCTL_API=3
  etcdctl set 键 “值”
  etcdctl get 键 
 例:[telecom@master ~]$ etcdctl set li "123"
123
[telecom@master ~]$ etcdctl get li
123

1.8 设置环境变量

vi /etc/profile中

加入 export ETCDCTL_API=3

执行source /etc/profile

 

如果报错,使用 journalctl -f -t etcd 和 journalctl -u etcd 来定位问题。

kubectl get cs命令 如果etcd不健康  查看/etc/etcd/etcd.conf配置文件
journalctl -f -t etcd 和 journalctl -u etcd命令找问题
 
[root@master ~]# vim /etc/systemd/system/etcd.service 
[Unit]
Description=etcd server
After=network.target
After=network-online.target
Wants=network-online.target
 
[Service]
#Type=simple
Type=notify
WorkingDirectory=/data/telecom/k8s/etcd1/data/default.etcd
EnvironmentFile=-/etc/etcd/etcd.conf
ExecStart=/usr/local/bin/etcd
[Install]
WantedBy=multi-user.target

Systemctl daemon-reload 
systemctl restart etcd.service
systemctl status etcd.service

kubectl get cs

 

2.安装kubernetes(即kubernetes-server)

2.1 解压kubernetes-server-linux-amd64.tar.gz 文件

进入到解压的目录,即

 

2.2 拷贝kube-apiserver文件

到/usr/local/bin/目录下或就在当前解压后的server目录下的bin下,本人的目录是在/data/telecom/k8s/kubernetes/server/bin

2.3 在/data/telecom/k8s/kubernetes下创建apiserver配置文件

[telecom@master ~]$ vim k8s/kubernetes/apiserver 
 
KUBE_API_ARGS="--storage-backend=etcd3 --etcd-servers=http://122.111.110.119:2379 --insecure-bind-address=0.0.0.0 --insecure-port=8080 --service-cluster-ip-range=10.10.10.0/24 --service-node-port-range=1-65535 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota --logtostderr=false --log-dir=/data/telecom/k8s/kubernetes/logs --v=2"

2.4 配置systemctl管理即建立kube-apiserver.service文件 [telecom@master ~]$ vim /etc/systemd/system/kube-apiserver.service

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=etcd.service
Wants=etcd.service
 
[Service]
EnvironmentFile=/data/telecom/k8s/kubernetes/apiserver
ExecStart=/data/telecom/k8s/kubernetes/server/bin/kube-apiserver $KUBE_API_ARGS
Restart=on-failure
Type=notify
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target

 

2.5 配置好后,执行以下命令:

systemctl daemon-reload
systemctl enable kube-apiserver.service
systemctl start kube-apiserver.service

systemctl status kube-apiserver.service

2.6查看kube-apiserver.service状态

通过curl命令访问API SERVER的数据,如下:

2.7 配置kube-scheduler配置文件

执行 touch /data/telecom/k8s/kubernetes/kube-scheduler
执行 vim kube-scheduler
[telecom@master ~]$ vim k8s/kubernetes/kube-scheduler 
KUBE_SCHEDULER_ARGS="--master=http://122.111.110.119:8080 --logtostderr=false --log-dir=/data/telecom/k8s/kubernetes/logs --v=2"

2.8 配置systemd服务文件kube-scheduler.service

即执行touch /etc/systemd/system/kube-scheduler.service
[telecom@master ~]$ vim /etc/systemd/system/kube-scheduler.service
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=kube-apiserver.service
Requires=kube-apiserver.service
[Service]
EnvironmentFile=/data/telecom/k8s/kubernetes/kube-scheduler
ExecStart=/data/telecom/k8s/kubernetes/server/bin/kube-scheduler $KUBE_SCHEDULER_ARGS
Restart=on-failure
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target

 

2.9 配置好后,启动服务,并设置开机启动

systemctl daemon-reload

systemctl enable kube-scheduler

systemctl restart kube-scheduler

 

2.10 创建kube-controller-manager配置文件

即执行 touch /data/telecom/k8s/kubernetes/kube-controller-manager 
编辑
[telecom@master ~]$ vim k8s/kubernetes/kube-controller-manager 
KUBE_CONTROLLER_MANAGER_ARGS="--master=http://122.111.110.119:8080 --logtostderr=false --log-dir=/data/telecom/k8s/kubernetes/logs --v=2"

2.11 配置systemd服务文件kube-controller-manager.service

[telecom@master ~]$ vim /etc/systemd/system/kube-controller-manager.service 
 
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=kube-apiserver.service
Requires=kube-apiserver.service
 
[Service]
EnvironmentFile=/data/telecom/k8s/kubernetes/kube-controller-manager
ExecStart=/data/telecom/k8s/kubernetes/server/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS
Restart=on-failure
LimitNOFILE=65536
 
[Install]
WantedBy=multi-user.target

 

2.12 启动服务,并设置开机启动

systemctl daemon-reload

systemctl enable kube-controller-manager

systemctl restart kube-controller-manager

 
 

3.kubernetes-server配置完成小结

Master节点组件就全部启动了,需要注意的是服务启动顺序有依赖,先启动etcd,再启动apiserver,其他组件无顺序要求。
OK,这样kubernetes的Master节点就搭建完毕了,接下来搭建Node节点,Node节点还是在同样的虚拟机上搭建,一般要求是Master和Node在不同的服务器上,但是K8s官方网站上说master和node在同一台机器上完全是没问题滴,所以也可以就在同一台服务器上部署的

3.1 查看Master节点组件进程状态

ps -ef |grep kube

说明组件都在运行。

3.2 如果启动失败,请查看启动日志

例如:

#journalctl -u kube-apiserver

七、node(即kubernetes-node)节点主机服务器的安装和配置

1 . node节点的介绍

在k8s集群中,每个Node节点都会启动kubelet进程,用来处理Master节点下发到本节点的任务,管理Pod和pod中的容器。kubelet会在API Server上注册节点信息,定期向Master汇报节点资源使用情况,并通过cAdvisor监控容器和节点资源。

2.解压node节点文件

 即tar kubernetes-node-linux-amd64.tar.gz, 解压kubernetes-node-linux-amd64.tar.gz 文件,拷贝kubelet到/usr/local/bin/或/data/telecom/k8s/kubernetes/node/bin/文件解压后的默认bin目录下

 

3.进入解压的目录kubernetes

即cd  kubernetes

4.默认或移动kubelet文件位置

即拷贝kubelet到/usr/local/bin/或/data/telecom/k8s/kubernetes/node/bin/文件解压后的默认bin目录下

5.创建连接master apiserver的kubelet配置文件,即kubelet.yaml

执行touch /data/telecom/k8s/kubernetes/kubelet.yaml

注:文件名可以是kubelet.yaml或kubelet.kubeconfig

kubelet.yaml文件用于kubelet连接master apiserver。

[telecom@node ~]$ vim k8s/kubernetes/kubelet.yaml

apiVersion: v1

kind: Config

clusters:

-  name: local

-  cluster:

server: http://122.111.110.119:8080

users:

-  name: kubelet

contexts:

-  context:

cluster: local

user: kubelet

-   name: kubelet-context

current-context: kubelet-context

6.创建kubelet配置文件

执行 touch  /data/telecom/k8s/kubernetes/kubelet

[telecom@node ~]$ vim k8s/kubernetes/kubelet

KUBELET_ARGS="--address=0.0.0.0 --port=10250 --hostname-override=122.111.110.120 --kubeconfig=/data/telecom/k8s/kubernetes/kubelet.yaml --allow-privileged=false --cluster-dns=10.10.10.2 --cluster-domain=cluster.local --fail-swap-on=false --logtostderr=true --log-dir=/data/telecom/k8s/kubernetes/logs --register-node=true --node-status-update-frequency=10s --runtime-cgroups=/lib/systemd/system/system.slice --kubelet-cgroups=/lib/systemd/system/system.slice --v=2 --pod-infra-container-image=k8s.gcr.io/pause-amd64:3.1"

#--api-servers=http://132.121.117.242

注意:--pod-infra-container-image=k8s.gcr.io/pause-amd64:3.1"

K8s依赖k8s.gcr.io/pause-amd64:3.1 本地物理机上必须要有这个镜像

7.配置systemd下的服务文件管理,即kubelet.service文件

执行touch /etc/systemd/system/kubelet.service

[telecom@node ~]$ vim /etc/systemd/system/kubelet.service

[Unit]

Description=Kubernetes Kubelet Server

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

After=docker.service

Requires=docker.service

[Service]

WorkingDirectory=/data/telecom/k8s/kubernetes/kubeletdata

EnvironmentFile=/data/telecom/k8s/kubernetes/kubelet

ExecStart=/data/telecom/k8s/kubernetes/node/bin/kubelet $KUBELET_ARGS

Restart=on-failure

KillMode=process

[Install]

WantedBy=multi-user.target

查看k8s日志

journalctl -xefu kubelet

8.创建kube-proxy配置文件

即执行touch   /data/telecom/k8s/kubernetes/kube-proxy

[telecom@node ~]$ vim k8s/kubernetes/kube-proxy

KUBE_PROXY_ARGS="--master=http://122.111.110.119:8080 --logtostderr=false --log-dir=/data/telecom/k8s/kubernetes/logs --v=2"

9.配置systemd下的服务管理kube-proxy.service

即执行touch /etc/systemd/system/kube-proxy.service

[telecom@node ~]$ vim /etc/systemd/system/kube-proxy.service

[Unit]

Description=Kubernetes Kube_Proxy Server

Documentation=https://github.com/GoogleCloudPlatform/kubernetes

After=network.target

Requires=network.service

[Service]

EnvironmentFile=/data/telecom/k8s/kubernetes/kube-proxy

ExecStart=/data/telecom/k8s/kubernetes/node/bin/kube-proxy $KUBE_PROXY_ARGS

Restart=on-failure

LimitNOFILE=65536

[Install]

WantedBy=multi-user.target

10. 配置完成后启动服务,并设置开机启动

systemctl daemon-reload

systemctl enable kube-proxy

systemctl restart kube-proxy

11. 查看Node节点组件进程状态

ps -ef |grep kube

说明组件都在运行。

12 如果启动失败,请查看启动日志

例如:

#journalctl -u kubelet

13. 验证集群是否部署成功

设置可执行文件到系统变量,方便使用:

# echo "export PATH=$PATH:/data/telecom/k8s/kubernetes/bin" >> /etc/profile
# source /etc/profile

14.在master机器上查看集群节点状态

执行kubectl get node

服务器没有该节点资源,解决如下:

设置eted的api=3的环境变量

[telecom@master ~]$ kubectl get node

NAME              STATUS    ROLES     AGE       VERSION

122.111.110.120   Ready     <none>    5d        v1.10.0

15 .node节点的小结

其他节点加入集群与node01方式相同,但需修改kubelet的--address和--hostname-override选项为本机IP

16.k8s启动服务的命令

systemctl daemon-reload
systemctl enable etcd.service
systemctl restart etcd.service
systemctl stop etcd.service

systemctl status etcd.service

 
systemctl daemon-reload
systemctl enable kube-apiserver.service
systemctl restart kube-apiserver.service

systemctl stop kube-apiserver.service

systemctl status kube-apiserver.service

curl http://localhost:8080/api/

systemctl daemon-reload
systemctl enable kube-controller-manager.service

systemctl stop kube-controller-manager.service

systemctl restart kube-controller-manager.service

systemctl status kube-controller-manager.service

systemctl daemon-reload
systemctl enable kube-scheduler.service

systemctl stop kube-scheduler.service

systemctl restart kube-scheduler.service

systemctl status kube-scheduler.service

systemctl daemon-reload
systemctl enable kubelet.service

systemctl stop kubelet.service

systemctl restart kubelet.service

systemctl status kubelet.service

systemctl daemon-reload
systemctl enable kube-proxy.service

systemctl stop kube-proxy.service

systemctl restart kube-proxy.service

systemctl status kube-proxy.service

八、设置网络(待修改中)

 1.设置etcd网络                                    

至此master配置完成,运行kubectl get nodes可以查看有多少minion在运行,以及其状态。这里我们的minion还都没有开始安装配置,所以运行之后结果为空

[root@master ~]# etcdctl set /atomic.io/network/config '{"Network":"172.17.0.0/16"}'

{"Network":"172.17.0.0/16"}

2.安装flannel

  配置kubernetes连接的服务端IP

3. 准备启动服务

(如果本来机器上已经运行过docker的请看过来,没有运行过的请忽略此步骤)

运行ifconfig,查看机器的网络配置情况(有docker0)

  warning:在运行过docker的机器上可以看到有docker0,这里在启动服务之前需要删掉docker0配置,在命令行运行:sudo ip link delete docker0

4.配置flannel网络

注:其中atomic.io与上面etcd中的Network对应

etcdctl mk /atomic.io/network/config '{"Network": "172.17.0.0/16"}'

[root@master ~]# vim /etc/sysconfig/flanneld

FLANNEL_ETCD_ENDPOINTS="http://122.111.110.119:2379"

FLANNEL_ETCD_PREFIX="/atomic.io/network"

九、Kubernetes之深入了解Pod及yaml脚本

1、yaml格式的Pod配置文件内容及注解

  深入Pod之前,首先我们来了解下Pod的yaml整体文件内容及功能注解。

如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

# yaml格式的pod定义文件完整内容:

apiVersion: v1       #必选,版本号,例如v1

kind: Pod       #必选,Pod

metadata:       #必选,元数据

name: string       #必选,Pod名称

namespace: string    #必选,Pod所属的命名空间

labels:      #自定义标签

- name: string     #自定义标签名字

annotations:       #自定义注释列表

- name: string

spec:         #必选,Pod中容器的详细定义

containers:      #必选,Pod中容器列表

- name: string     #必选,容器名称

image: string    #必选,容器的镜像名称

imagePullPolicy: [Always | Never | IfNotPresent]

#获取镜像的策略

Alawys表示下载镜像

IfnotPresent表示优先使用本地镜像,否则下载镜像,

Nerver表示仅使用本地镜像

command: [string]    #容器的启动命令列表,如不指定,使用打包时使用的启动命令

args: [string]     #容器的启动命令参数列表

workingDir: string     #容器的工作目录

volumeMounts:    #挂载到容器内部的存储卷配置

- name: string     #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名

mountPath: string    #存储卷在容器内mount的绝对路径,应少于512字符

readOnly: boolean    #是否为只读模式

ports:       #需要暴露的端口库号列表

- name: string     #端口号名称

containerPort: int   #容器需要监听的端口号

hostPort: int    #容器所在主机需要监听的端口号,默认与Container相同

protocol: string     #端口协议,支持TCP和UDP,默认TCP

env:       #容器运行前需设置的环境变量列表

- name: string     #环境变量名称

value: string    #环境变量的值

resources:       #资源限制和请求的设置

limits:      #资源限制的设置

cpu: string    #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数

memory: string     #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数

requests:      #资源请求的设置

cpu: string    #Cpu请求,容器启动的初始可用数量

memory: string     #内存清楚,容器启动的初始可用数量

livenessProbe:     #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可

exec:      #对Pod容器内检查方式设置为exec方式

command: [string]  #exec方式需要制定的命令或脚本

httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port

path: string

port: number

host: string

scheme: string

HttpHeaders:

- name: string

value: string

tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式

port: number

initialDelaySeconds: 0  #容器启动完成后首次探测的时间,单位为秒

timeoutSeconds: 0   #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒

periodSeconds: 0    #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次

successThreshold: 0

failureThreshold: 0

securityContext:

privileged:false

restartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod

nodeSelector: obeject  #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定

imagePullSecrets:    #Pull镜像时使用的secret名称,以key:secretkey格式指定

- name: string

hostNetwork:false      #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络

volumes:       #在该pod上定义共享存储卷列表

- name: string     #共享存储卷名称 (volumes类型有很多种)

emptyDir: {}     #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值

hostPath: string     #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录

path: string     #Pod所在宿主机的目录,将被用于同期中mount的目录

secret:      #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部

scretname: string

items:

- key: string

path: string

configMap:     #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部

name: string

items:

- key: string

path: string

 

2、Pod基本用法:

  在使用docker时,我们可以使用docker run命令创建并启动一个容器,而在Kubernetes系统中对长时间运行的容器要求是:其主程序需要一直在前台运行。如果我们创建的docker镜像的启动命令是后台执行程序,例如Linux脚本:

  nohup ./startup.sh &

  则kubelet创建包含这个容器的pod后运行完该命令,即认为Pod执行结束,之后根据RC中定义的pod的replicas副本数量生产一个新的pod,而一旦创建出新的pod,将在执行完命令后陷入无限循环的过程中,这就是Kubernetes需要我们创建的docker镜像以一个前台命令作为启动命令的原因。

对于无法改造为前台执行的应用,也可以使用开源工具supervisor辅助进行前台运行的功能。

Pod可以由一个或多个容器组合而成

例如:两个容器应用的前端frontend和redis为紧耦合的关系,应该组合成一个整体对外提供服务,则应该将这两个打包为一个pod.

配置文件frontend-localredis-pod.yaml如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

apiVersion:v1

kind: Pod

metadata:

name: redis-php

label:

name: redis-php

spec:

containers:

- name: frontend

image: kubeguide/guestbook-php-frontend:localredis

ports:

- containersPort: 80

- name: redis-php

image:kubeguide/redis-master

ports:

- containersPort: 6379

  

  属于一个Pod的多个容器应用之间相互访问只需要通过localhost就可以通信,这一组容器被绑定在一个环境中。

  使用kubectl create创建该Pod后,get Pod信息可以看到如下图:

1

2

3

#kubectl get gods

NAME READY STATUS RESTATS AGE

redis-php 2/2Running 0 10m

  可以看到READY信息为2/2,表示Pod中的两个容器都成功运行了.

  查看pod的详细信息,可以看到两个容器的定义和创建过程。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

[root@kubernetes-master ~]# kubectl describe redis-php

the server doesn't have a resourcetype "redis-php"

[root@kubernetes-master ~]# kubectl describe pod redis-php

Name: redis-php

Namespace: default

Node: kubernetes-minion/10.0.0.23

Start Time: Wed, 12 Apr 2017 09:14:58 +0800

Labels: name=redis-php

Status: Running

IP: 10.1.24.2

Controllers: <none>

Containers:

nginx:

ContainerID: docker://d05b743c200dff7cf3b60b7373a45666be2ebb48b7b8b31ce0ece9be4546ce77

Image: nginx

Image ID: docker-pullable://docker.io/nginx@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582

Port: 80/TCP

State: Running

Started: Wed, 12 Apr 2017 09:19:31 +0800

  3、静态Pod

  静态pod是由kubelet进行管理的仅存在于特定Node的Pod上,他们不能通过API Server进行管理,无法与ReplicationController、Deployment或者DaemonSet进行关联,并且kubelet无法对他们进行健康检查。静态Pod总是由kubelet进行创建,并且总是在kubelet所在的Node上运行。

创建静态Pod有两种方式:配置文件或者HTTP方式

1)配置文件方式

  首先,需要设置kubelet的启动参数"--config",指定kubelet需要监控的配置文件所在的目录,kubelet会定期扫描该目录,冰根据目录中的 .yaml或 .json文件进行创建操作

假设配置目录为/etc/kubelet.d/配置启动参数:--config=/etc/kubelet.d/,然后重启kubelet服务后,再宿主机受用docker ps或者在Kubernetes Master上都可以看到指定的容器在列表中

由于静态pod无法通过API Server直接管理,所以在master节点尝试删除该pod,会将其变为pending状态,也不会被删除

1

2

3

4

5

#kubetctl delete pod static-web-node1

pod "static-web-node1"deleted

#kubectl get pods

NAME READY STATUS RESTARTS AGE

static-web-node1 0/1Pending 0 1s

  

  要删除该pod的操作只能在其所在的Node上操作,将其定义的.yaml文件从/etc/kubelet.d/目录下删除

1

2

#rm -f /etc/kubelet.d/static-web.yaml

#docker ps

  

4、Pod容器共享Volume

  Volume类型包括:emtyDir、hostPath、gcePersistentDisk、awsElasticBlockStore、gitRepo、secret、nfs、scsi、glusterfs、persistentVolumeClaim、rbd、flexVolume、cinder、cephfs、flocker、downwardAPI、fc、azureFile、configMap、vsphereVolume等等,可以定义多个Volume,每个Volume的name保持唯一。在同一个pod中的多个容器能够共享pod级别的存储卷Volume。Volume可以定义为各种类型,多个容器各自进行挂载操作,讲一个Volume挂载为容器内需要的目录。

如下图:

  如上图中的Pod中包含两个容器:tomcat和busybox,在pod级别设置Volume “app-logs”,用于tomcat想其中写日志文件,busybox读日志文件。

配置文件如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

apiVersion:v1

kind: Pod

metadata:

name: redis-php

label:

name: volume-pod

spec:

containers:

- name: tomcat

image: tomcat

ports:

- containersPort: 8080

volumeMounts:

- name: app-logs

mountPath:/usr/local/tomcat/logs

- name: busybox

image:busybox

command: ["sh","-C","tail -f /logs/catalina*.log"]

volumes:

- name: app-logs

emptyDir:{}

busybox容器可以通过kubectl logs查看输出内容

1

#kubectl logs volume-pod -c busybox 

tomcat容器生成的日志文件可以登录容器查看

1

#kubectl exec -ti volume-pod -c tomcat -- ls /usr/local/tomcat/logs

5.Pod的配置管理

  应用部署的一个最佳实践是将应用所需的配置信息于程序进行分离,这样可以使得应用程序被更好的复用,通过不用配置文件也能实现更灵活的功能。将应用打包为容器镜像后,可以通过环境变量或外挂文件的方式在创建容器时进行配置注入。ConfigMap是Kubernetes v1.2版本开始提供的一种统一集群配置管理方案。

  5.1 ConfigMap:容器应用的配置管理

  容器使用ConfigMap的典型用法如下:

  (1)生产为容器的环境变量。

  (2)设置容器启动命令的启动参数(需设置为环境变量)。

  (3)以Volume的形式挂载为容器内部的文件或目录。

  ConfigMap以一个或多个key:value的形式保存在Kubernetes系统中共应用使用,既可以用于表示一个变量的值,也可以表示一个完整的配置文件内容。

通过yuaml配置文件或者直接使用kubelet create configmap 命令的方式来创建ConfigMap

  5.2 ConfigMap的创建

   举个小例子cm-appvars.yaml来描述将几个应用所需的变量定义为ConfigMap的用法:

1

2

3

4

5

6

7

8

# vim cm-appvars.yaml

apiVersion: v1

kind: ConfigMap

metadata:

name: cm-appvars

data:

apploglevel: info

appdatadir:/var/data

 

  执行kubectl create命令创建该ConfigMap

1

2

#kubectl create -f cm-appvars.yaml

configmap "cm-appvars.yaml"created

  查看建立好的ConfigMap:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

#kubectl get configmap

NAME DATA AGE

cm-appvars 2 3s

[root@kubernetes-master ~]# kubectl describe configmap cm-appvars

Name: cm-appvars

Namespace: default

Labels: <none>

Annotations: <none>

Data

====

appdatadir: 9 bytes

apploglevel: 4 bytes

[root@kubernetes-master ~]# kubectl get configmap cm-appvars -o yaml

apiVersion: v1

data:

appdatadir: /var/data

apploglevel: info

kind: ConfigMap

metadata:

creationTimestamp: 2017-04-14T06:03:36Z

name: cm-appvars

namespace: default

resourceVersion:"571221"

selfLink: /api/v1/namespaces/default/configmaps/cm-appvars

uid: 190323cb-20d8-11e7-94ec-000c29ac8d83 

  另:创建一个cm-appconfigfile.yaml描述将两个配置文件server.xml和logging.properties定义为configmap的用法,设置key为配置文件的别名,value则是配置文件的文本内容:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

apiVersion: v1

kind: ConfigMap

metadata:

name: cm-appvars

data:

key-serverxml:

<?xml Version='1.0'encoding='utf-8'?>

<Server port="8005"shutdown="SHUTDOWN">

.....

</service>

</Server>

key-loggingproperties:

"handlers=lcatalina.org.apache.juli.FileHandler,

...."

  在pod "cm-test-app"定义中,将configmap "cm-appconfigfile"中的内容以文件形式mount到容器内部configfiles目录中。

Pod配置文件cm-test-app.yaml内容如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#vim cm-test-app.yaml

apiVersion: v1

kind: Pod

metadata:

name: cm-test-app

spec:

containers:

- name: cm-test-app

image: tomcat-app:v1

ports:

- containerPort: 8080

volumeMounts:

- name: serverxml                          #引用volume名

mountPath:/configfiles                       #挂载到容器内部目录

configMap:

name: cm-test-appconfigfile                  #使用configmap定义的的cm-appconfigfile

items:

- key: key-serverxml                     #将key=key-serverxml

path: server.xml                           #value将server.xml文件名进行挂载

- key: key-loggingproperties                 #将key=key-loggingproperties

path: logging.properties                   #value将logging.properties文件名进行挂载 

  创建该Pod:

1

2

#kubectl create -f cm-test-app.yaml

Pod "cm-test-app"created  

  登录容器查看configfiles目录下的server.xml和logging.properties文件,他们的内容就是configmap “cm-appconfigfile”中定义的两个key的内容

1

2

3

#kubectl exec -ti cm-test-app -- bash

root@cm-rest-app:/# cat /configfiles/server.xml

root@cm-rest-app:/# cat /configfiles/logging.properties

  5.3使用ConfigMap的条件限制

  使用configmap的限制条件如下:

configmap必须在pod之间创建

configmap也可以定义为属于某个Namespace,只有处于相同namespaces中的pod可以引用

configmap中配额管理还未能实现

kubelet只支持被api server管理的pod使用configmap,静态pod无法引用

在pod对configmap进行挂载操作时,容器内部职能挂载为目录,无法挂载文件。

6.Pod生命周期和重启策略

  Pod在整个生命周期过程中被定义为各种状态,熟悉Pod的各种状态有助于理解如何设置Pod的调度策略、重启策略

  Pod的状态包含以下几种,如图:

  

  Pod的重启策略(RestartPolicy)应用于Pod内所有的容器,并且仅在Pod所处的Node上由kubelet进行判断和重启操作。当某哥容器异常退出或者健康检查石柏师,kubelet将根据RestartPolicy的设置进行相应的操作

  Pod的重启策略包括Always、OnFailure及Nerver,默认值为Always。

  kubelet重启失效容器的时间间隔以sync-frequency乘以2n来计算,例如1、2、4、8倍等,最长延时5分钟,并且成功重启后的10分钟后重置该事件。

  Pod的重启策略和控制方式息息相关,当前可用于管理Pod的控制器宝库ReplicationController、Job、DaemonSet及直接通过kubelet管理(静态Pod),每种控制器对Pod的重启策略要求如下:

RC和DaemonSet:必须设置为Always,需要保证该容器持续运行

Job:OnFailure或Nerver,确保容器执行完成后不再重启

kubelet:在Pod失效时重启他,不论RestartPolicy设置什么值,并且也不会对Pod进行健康检查

7、Pod健康检查

  对Pod的健康检查可以通过两类探针来检查:LivenessProbe和ReadinessProbe

LivenessProbe探针:用于判断容器是否存活(running状态),如果LivenessProbe探针探测到容器不健康,则kubelet杀掉该容器,并根据容器的重启策略做响应处理

ReadinessProbe探针:用于判断容器是否启动完成(ready状态),可以接受请求。如果ReadinessProbe探针探测失败,则Pod的状态被修改。Endpoint Controller将从service的Endpoint中删除包含该容器所在的Pod的Endpoint。

  kubelet定制执行LivenessProbe探针来诊断容器的健康状况。LivenessProbe有三种事项方式。

7.1 ExecAction

在容器内部执行一个命令,如果该命令的返回值为0,则表示容器健康

例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

apiVersion:v1

kind: Pod

metadata:

name: liveness-exec

label:

name: liveness

spec:

containers:

- name: tomcat

image: grc.io/google_containers/tomcat

args:

-/bin/sh

- -c

-echo ok >/tmp.health;sleep10; rm -fr /tmp/health;sleep600

livenessProbe:

exec:

command:

-cat

-/tmp/health

initianDelaySeconds:15

timeoutSeconds:1 

7.2 TCPSocketAction

通过容器ip地址和端口号执行TCP检查,如果能够建立tcp连接表明容器健康

例:

1

2

3

4

5

6

7

8

9

10

11

12

kind: Pod

metadata:

name: pod-with-healthcheck

spec:

containers:

- name: nginx

image: nginx

livenessProbe:

tcpSocket:

port: 80

initianDelaySeconds:30

timeoutSeconds:1

7.3 HTTPGetAction

通过容器Ip地址、端口号及路径调用http get方法,如果响应的状态吗大于200且小于400,则认为容器健康

例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

apiVersion:v1

kind: Pod

metadata:

name: pod-with-healthcheck

spec:

containers:

- name: nginx

image: nginx

livenessProbe:

httpGet:

path:/_status/healthz

port: 80

initianDelaySeconds:30

timeoutSeconds:1

  

对于每种探针方式,都需要设置initialDelaySeconds和timeoutSeconds两个参数,它们含义如下:

initialDelaySeconds:启动容器后首次监控检查的等待时间,单位秒

timeouSeconds:健康检查发送请求后等待响应的超时时间,单位秒。当发生超时就被认为容器无法提供服务无,该容器将被重启

8.玩转Pod调度

  在Kubernetes系统中,Pod在大部分场景下都只是容器的载体而已,通常需要通过RC、Deployment、DaemonSet、Job等对象来完成Pod的调度和自动控制功能。

8.1 RC、Deployment:全自动调度

  RC的主要功能之一就是自动部署容器应用的多份副本,以及持续监控副本的数量,在集群内始终维护用户指定的副本数量。

在调度策略上,除了使用系统内置的调度算法选择合适的Node进行调度,也可以在Pod的定义中使用NodeSelector或NodeAffinity来指定满足条件的Node进行调度。

  1)NodeSelector:定向调度

  Kubernetes Master上的scheduler服务(kube-Scheduler进程)负责实现Pod的调度,整个过程通过一系列复杂的算法,最终为每个Pod计算出一个最佳的目标节点,通常我们无法知道Pod最终会被调度到哪个节点上。实际情况中,我们需要将Pod调度到我们指定的节点上,可以通过Node的标签和pod的nodeSelector属性相匹配来达到目的。

  (1)首先通过kubectl label命令给目标Node打上标签

kubectl label nodes <node-name> <label-key>=<label-value>

例:

1

#kubectllabel nodes k8s-node-1 zonenorth

  (2)然后在Pod定义中加上nodeSelector的设置

例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

apiVersion:v1

kind: Pod

metadata:

name: redis-master

label:

name: redis-master

spec:

replicas: 1

selector:

name: redis-master

template:

metadata:

labels:

name: redis-master

spec:

containers:

- name: redis-master

images: kubeguide/redis-master

ports:

- containerPort: 6379

nodeSelector:

zone: north 

运行kubectl create -f命令创建Pod,scheduler就会将该Pod调度到拥有zone=north标签的Node上。 如果多个Node拥有该标签,则会根据调度算法在该组Node上选一个可用的进行Pod调度。

需要注意的是:如果集群中没有拥有该标签的Node,则这个Pod也无法被成功调度。

  2)NodeAffinity:亲和性调度

该调度策略是将来替换NodeSelector的新一代调度策略。由于NodeSelector通过Node的Label进行精确匹配,所有NodeAffinity增加了In、NotIn、Exists、DoesNotexist、Gt、Lt等操作符来选择Node。调度侧露更加灵活。

8.2 DaemonSet:特定场景调度

DaemonSet用于管理集群中每个Node上仅运行一份Pod的副本实例,如图

这种用法适合一些有下列需求的应用:

在每个Node上运行个以GlusterFS存储或者ceph存储的daemon进程

在每个Node上运行一个日志采集程序,例如fluentd或者logstach

在每个Node上运行一个健康程序,采集Node的性能数据。

DaemonSet的Pod调度策略类似于RC,除了使用系统内置的算法在每台Node上进行调度,也可以在Pod的定义中使用NodeSelector或NodeAffinity来指定满足条件的Node范围来进行调度。

8.3 批处理调度

9.Pod的扩容和缩荣

  在实际生产环境中,我们经常遇到某个服务需要扩容的场景,也有可能因为资源精确需要缩减资源而需要减少服务实例数量,此时我们可以Kubernetes中RC提供scale机制来完成这些工作。

以redis-slave RC为例,已定义的最初副本数量为2,通过kubectl scale命令可以将Pod副本数量重新调整

1

2

3

4

5

6

7

#kubectl scale rc redis-slave --replicas=3

ReplicationController"redis-slave" scaled

#kubectl get pods

NAME READY STATUS RESTARTS AGE

redis-slave-1sf23 1/1Running 0 1h

redis-slave-54wfk 1/1Running 0 1h

redis-slave-3da5y 1/1Running 0 1h 

  除了可以手工通过kubectl scale命令完成Pod的扩容和缩容操作以外,新版本新增加了Horizontal Podautoscaler(HPA)的控制器,用于实现基于CPU使用路进行启动Pod扩容缩容的功能。该控制器基于Mastger的kube-controller-manager服务启动参数 --horizontal-pod-autoscler-sync-period定义的时长(默认30秒),周期性监控目标Pod的Cpu使用率并在满足条件时对ReplicationController或Deployment中的Pod副本数量进行调整,以符合用户定义的平均Pod Cpu使用率,Pod Cpu使用率来源于heapster组件,所以需预先安装好heapster。

10.Pod的滚动升级

  当集群中的某个服务需要升级时,我们需要停止目前与该服务相关的所有Pod,然后重新拉取镜像并启动。如果集群规模较大,因服务全部停止后升级的方式将导致长时间的服务不可用。由此,Kubernetes提供了rolling-update(滚动升级)功能来解决该问题。

滚动升级通过执行kubectl rolling-update命令一键完成,该命令创建一个新的RC,然后自动控制旧版本的Pod数量逐渐减少到0,同时新的RC中的Pod副本数量从0逐步增加到目标值,最终实现Pod的升级。需要注意的是,系统要求新的RC需要与旧的RC在相同的Namespace内,即不能把别人的资产转到到自家名下。

  例:将redis-master从1.0版本升级到2.0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

apiVersion: v1

kind: replicationController

metadata:

name: redis-master-v2

labels:

name: redis-master

Version: v2

spec:

replicas: 1

selector:

name: redis-master

Version: v2

template:

labels:

name: redis-master

Version: v2

spec:

containers:

- name: master

images: kubeguide/redis-master:2.0

ports:

- containerPort: 6379

  需要注意的点:

  (1)RC的name不能与旧的RC名字相同

  (2)在sele中应至少有一个label与旧的RC的label不同,以标识为新的RC。本例中新增了一个名为version的label与旧的RC区分

  运行kubectl rolling-update来完成Pod的滚动升级:

1

#kubectl rolling-update redis-master -f redis-master-controller-v2.yaml

  另一种方法就是不使用配置文件,直接用kubectl rolling-update加上--image参数指定新版镜像名来完成Pod的滚动升级

1

#kubectl rolling-update redis-master --image=redis-master:2.0

  与使用配置文件的方式不同的是,执行的结果是旧的RC被删除,新的RC仍然使用就的RC的名字。

  如果在更新过程总发现配置有误,则用户可以中断更新操作,并通过执行kubectl rolling-update-rollback完成Pod版本的回滚。

十、为什么要用k8s

最根本的理由是:it是由技术驱动的行业

1、用k8s由以下几点好处

1.1 可以轻装上阵

相比其他的来说,维护只需要少量的人员都可以完成复杂的系统

1.2. k8s全面拥抱微服务架构

微服务架构核心就是将一个巨大的单体应用分解成多个互相连接的小的服务,一个微服务可能需要多个副本支撑,随着数量的增加及系统负荷的调整,内嵌的负载均衡就有很大的作用

1.3 方便快捷

可以随时随地的搬迁到公有云上

1.4 k8s系统架构有超前的横向扩展能力

对于网络公司来说,用户规模就等价于资产,一个小集群node就可以平滑扩展为上百个node的大规模集群中

十一、k8s在实际应用中解决的主要问题

1问题一 k8s是否能完成负载均衡功能(步骤,种类,优缺点)

1.1 Kubernetes的负载均衡(Nginx Ingress)

Kubernetes关于服务的暴露主要是通过NodePort方式,通过绑定node主机的某个端口,然后进行pod的请求转发和负载均衡,但这种方式下缺陷是

  • Service可能有很多个,如果每个都绑定一个node主机端口的话,主机需要开放外围一堆的端口进行服务调用,管理混乱
  • 无法应用很多公司要求的防火墙规则

理想的方式是通过一个外部的负载均衡器,绑定固定的端口,比如80,然后根据域名或者服务名向后面的Service ip转发,Nginx很好的解决了这个需求,但问题是如果有新的服务加入,如何去修改Nginx的配置,并且加载这些配置? Kubernetes给出的方案就是Ingress,Ingress包含了两大主件Ingress Controller和Ingress.

  • Ingress解决的是新的服务加入后,域名和服务的对应问题,基本上是一个ingress的对象,通过yaml进行创建和更新进行加载。
  • Ingress Controller是将Ingress这种变化生成一段Nginx的配置,然后将这个配置通过Kubernetes API写到Nginx的Pod中,然后reload.

1.1.1 具体实现

1.生成一个默认的后端,如果遇到解析不到的URL就转发到默认后端页面

[root@master ingress]# cat default-backend.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: default-http-backend
  labels:
    k8s-app: default-http-backend
  namespace: kube-system
spec:
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: default-http-backend
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: default-http-backend
        # Any image is permissable as long as:
        # 1. It serves a 404 page at /
        # 2. It serves 200 on a /healthz endpoint
        image: gcr.io/google_containers/defaultbackend:1.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: 10m
            memory: 20Mi
          requests:
            cpu: 10m
            memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  namespace: kube-system
  labels:
    k8s-app: default-http-backend
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    k8s-app: default-http-backend

1.1.2 部署Ingress Controller

地址https://github.com/kubernetes/ingress/blob/master/examples/daemonset/nginx/nginx-ingress-daemonset.yaml

[root@k8s-master ingress]# cat nginx-ingress-controller.yaml 
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-ingress-lb
  labels:
    name: nginx-ingress-lb
  namespace: kube-system
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: nginx-ingress-lb
      annotations:
        prometheus.io/port: '10254'
        prometheus.io/scrape: 'true'
    spec:
      terminationGracePeriodSeconds: 60
      hostNetwork: true
      containers:
      - image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.7(本地要有的镜像)
        name: nginx-ingress-lb
        readinessProbe:
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
        livenessProbe:
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          timeoutSeconds: 1
        ports:
        - containerPort: 80
          hostPort: 80
        - containerPort: 443
          hostPort: 443
        env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: KUBERNETES_MASTER
            value: http://132.121.117.242:8080
        args:
        - /nginx-ingress-controller
        - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
        - --apiserver-host=http://132.121.117.242:8080

问题是,启动后pod总是在CrashLoopBack的状态,通过logs一看发现nginx-ingress-controller的启动总是去连接apiserver内部集群ip的443端口,导致因为安全问题不让启动,后来在args里面加入

- --apiserver-host=http://132.121.117.242:8080

后成功启动.

Kubectl get pods -n kube-system

1.1.3.配置ingress

配置如下

[root@master ingress]# cat dashboard-web.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dashboard-web-ingress
  namespace: kube-system
spec:
  rules:
  - host: 10.10.12.1
    http:
      paths:
      - path: /console
        backend:
          serviceName: helloworldsvc 
          servicePort: 7001
      - path: /
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 80

理解如下:

  • host指虚拟出来的域名,具体地址(是Ingress-controller那台Pod所在的主机的地址)应该加入/etc/hosts中,这样所有去10.10.12.1的请求都会发到nginx
  • path:/console匹配后面的应用路径
  • servicePort主要是定义服务的时候的端口,不是NodePort.
  • path:/ 匹配后面dashboard应用的路径,以前通过访问master节点8080/ui进入dashboard的,但dashboard其实是部署在node节点中,实际是通过某个路由语句转发过去而已

而yaml文件是

[root@k8s-master ~]# cat kubernetes-dashboard.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
# Keep the name in sync with image version and
# gce/coreos/kube-manifests/addons/dashboard counterparts
  name: kubernetes-dashboard-latest
  namespace: kube-system
spec:
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
        version: latest
        kubernetes.io/cluster-service: "true"
    spec:
      containers:
      - name: kubernetes-dashboard
        image: gcr.io/google_containers/kubernetes-dashboard-amd64:v1.5.1
        resources:
          # keep request = limit to keep this container in guaranteed class
          limits:
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
        ports:
        - containerPort: 9090
        args:
         -  --apiserver-host=http://132.121.117.242:8080
        livenessProbe:
          httpGet:
            path: /
            port: 9090
          initialDelaySeconds: 30
          timeoutSeconds: 30
---
kind: Service
metadata:
  name: kubernetes-dashboard
  namespace: kube-system
  labels:
    k8s-app: kubernetes-dashboard
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    k8s-app: kubernetes-dashboard
  ports:
  - port: 80
    targetPort: 9090

所以访问132.121.117.242:9090端口就会出现dashboard

1.1.4.测试 

Ok,一切就绪

访问http://132.121.117.242/    出现dashboard

1.1.5.配置TLS SSL访问

TLS的配置相当于Web中证书的配置,配置过程如下

  • 证书生成
# 生成 CA 自签证书
mkdir cert && cd cert
openssl genrsa -out ca-key.pem 2048
openssl req -x509 -new -nodes -key ca-key.pem -days 10000 -out ca.pem -subj "/CN=kube-ca"
 
# 编辑 openssl 配置
cp /etc/pki/tls/openssl.cnf .
vim openssl.cnf
 
# 主要修改如下
[req]
req_extensions = v3_req # 这行默认注释关着的 把注释删掉
# 下面配置是新增的
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = 132.121.117.242
#DNS.2 = kibana.mritd.me
DNS.2=10.10.12.1
 
# 生成证书
openssl genrsa -out ingress-key.pem 2048
openssl req -new -key ingress-key.pem -out ingress.csr -subj "/CN=helloworld.eric" -config openssl.cnf
openssl x509 -req -in ingress.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out ingress.pem -days 365 -extensions v3_req -extfile openssl.cnf

需要注意的是DNS需要修改成自己的host名,然后在配置csr证书请求的时候需要将域名或者访问名带入subj,比如

-subj "/CN=132.121.117.242" 
  • 创建secret
kubectl create secret tls ingress-secret --namespace=kube-system --key cert/ingress-key.pem --cert cert/ingress.pem 
  • 修改Ingress文件启用证书
[root@k8s-master ingress]# cat tls-weblogic.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dashboard-weblogic-ingress
  namespace: kube-system
spec:
  tls:
  - hosts:
    - k8s-master
    secretName: ingress-secret
  rules:
  - host: 132.121.117.242或k8s-master
    http:
      paths:
      - path: /console
        backend:
          serviceName: helloworldsvc 
          servicePort: 7001
      - path: /
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 80

1.2用nginx的ngx_upstream_jdomain模块实现k8s容器的负载均衡

1.2.1使用背景

ingress controller其实也是通过nginx来实现的,但是Ingress本身依赖于service,它通过查询service的映射,来找到service后端的pod的真实ip,并将其挂载到ingress controll的upstream中来实现负载均衡。这本身其实并没有什么问题。但由于在我们的k8s中,鉴于标准service基于kube-proxy的转发效率不高,我们放弃了标准service。转而直接采用了headless service的方式。这种方式的好处是,dns解析会直接解析到每个pod的ip,而不再解析到service ip,也不再需要kube-proxy来实现转发。缺点是负载均衡只能依赖dns轮循,没有灵活的调度策略,但毫无疑问,由于去除了kube-proxy这个中间层,转发效率得到了提高。另外,由于我们直接打通了Pod与物理服务器之间的网络,物理网络中的主机可以与Pod之间通信,如果在中间采用标准的service,service的ip反而无法与物理网络直接实现通信。

这样一来,我们外部的负载均衡就没办法再去依赖Ingress了,我们采用了在外部部署nginx来实现负载均衡的方法,由于upstream里的pod ip会动态变化,所以我们不能直接在upstream里写死pod的ip地址,而只能用service的域名来替代,并让nginx自己去解析这个域名,我们知道headless service的域名由于没有内部的service ip,所以是直接解析到pod ip上的,这样就等于动态拿到了pod ip。在这种情况下,nginx_upstream_jdomain模块就登场了。
1.2.2 配置

在具体的配置之前,nginx_upstream_jdomain这个模块严重依赖dns解析,另外由于其代理的后端的upstream中的pod ip经常性发生变化,所以dns缓存时间还不能太长,不过这个可以在nginx_upstream_jdomain模块参数中配置

ngx_upstream_jdomain的详细配置:https://www.nginx.com/resources/wiki/modules/domain_resolve/

1.2.2配置:

http{

resolver 132.121.117.242;
resolver_timeout 3s;
upstream pod {
  jdomain 132.121.117.242 port=8899 interval=20;  #每隔20s做一次解析
}
 
server {
  server_name 132.121.117.242;
  listen 8899;
  #set $proxy_upstream_name "-";
  location / {
 
    #Proxy Settings
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header CDN-SRC-IP $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
    proxy_max_temp_file_size 0;
    proxy_connect_timeout 30;
    proxy_send_timeout 90;
    proxy_read_timeout 90;
    proxy_buffer_size 4k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k;
 
    proxy_pass http://pod;
  }
 
}

备注:通过这种方式代理到后端的服务,后端服务接收到的$host的值即为www-stress-80,在代理配置中,必须加上如下配置以将主机头传递给后端服务器:

proxy_set_header Host $host;

1.3  service负载

touch pod-svc.yaml

vim pod-svc.yaml

apiVersion: v1

kind: Service

metadata:

name: demo-client

namespace: demo

labels:

service: demo-client

spec:

selector:

app: demo-client

ports:

- name: http

port: 3000

targetPort: 3000

protocol: TCP

clusterIP:  11.0.0.98

sessionAffinity: ClientIP

备注:

sessionAffinity可指定ClientIP或者None
默认是根据kube-proxy的负载均衡策略,随机分配

如果外部访问 加type:NodePort   nodePort:3000

1.4 负载分发策略

RoundRobin:轮询模式,轮询请求转发到后端的pod

sessionAffinity:基于客户端ip地址进行会话保持模式,就是第一次将客户端发起的请求转发到后端某个pod,之后从相同的客户端请求都转发到后端相同的pod

默认是RoundRobin 但可是设置service.spec. sessionAffinity= ClientIP来启用

2.问题二 是否能分群,如何分

3.问题三 项目版本如何更新(如何操作)

3.1 pod升级与回滚

3.1.1 Deployment的升级(pod)

vim nginx-deployment.yaml

apiVersion: apps/v1beta1reen-service.yaml

kind: Deployment

metadata:

 name: nginx-deployment

spec:

replicas: 1

template:

metadata:

labels:

app: nginx

spec:

containers:

- name: nginx

images: nginx:1.13.9

ports:

- containerPort: 80

通过kubectl set image命令为Deployment设置新的镜像名称,比如升级为1.14.1

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

使用kubectl edit命令修改Deployment的配置 将spec.template.spec.containers[0].images 从nginx:1.13.9更改为1.14.1; 保存退出后,kubernetes会自动升级镜像

即kubectl edit deployment/nginx-deployment

查看运行节点

Kubectl get pods

查看使用的镜像

Kubectl  describe pod名

1.Recreate(重建): 设置spec.strategy.type=Recreate,表示Deployment在更新Pod时,会先杀掉所有正在运行的Pod,然后创建新的Pod.

2.RollingUpdate(滚动更新):以滚动更新的方式来逐个更新Pod,可以通过设置spec.strategy.rollingUpdate下的两个参数(maxUnavailable和maxSurge)来控制滚动更新的过程。

3.1.2 回滚

比如说 误设置nginx:1.14.1镜像

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

查看deployment的回滚的状态

kubectl rollout status deployment/nginx-deployment

查看历史记录

Kubectl rollout history  检查Deployment部署历史记录

例如:Kubectl rollout history deployment/nginx-deployment

查看特定版本用--revision=n 参数

Kubectl rollout history deployment/nginx-deployment --revision=3

撤销本次发布并回滚到上一个版本

Kubectl rollout undo deployment/nginx-deployment

回滚版本号

Kubectl rollout undo deployment/nginx-deployment --to—revision=2

暂停更新

Kubectl rollout pause deployment/nginx-deployment

暂停时可任意次数更新配置

例:kubectl set resources deployment nginx-deployment -c=nginx –limits=cpu=200m,memory=512Mi

恢复操作

Kubectl rollout resume deploy nginx-deployment

4.如何扩容(增加或减少节点)

4.1 扩容或缩容

4.1.1 手动扩容

Vim pod.yaml

apiVersion: apps/v1beta1

kind: Deployment

metadata:

 name: nginx-deployment

spec:

replicas:

template:

metadata:

labels:

app: nginx

spec:

containers:

- name: nginx

images: nginx:1.13.9

ports:

- containerPort: 80

注:replicas: 数字1变5即replicas: 5 ,就是5个pod 扩容

replicas: 数字5变1即replicas: 1 ,就是1个pod 缩容

4.1.2 自动扩容

4.2 蓝绿部署

4.2.1蓝部署

Vim bule.yaml

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: nginx-1.13.9

spec: replicas: 3

template:

metadata:

labels:

name: nginx

version: "1.13.9"

spec:

containers:

- name: nginx

image: nginx:1.13.9

ports:

- name: http

containerPort: 80

执行kubectl apply -f bule.yaml

注:一旦部署,可以通过创建一个服务来提供访问部署实例的方法。服务与部署分离,指定一个标签选择器,它的主要作用是列出构成服务的pods

创建bule-service.yaml

Vim bule-service.yaml

apiVersion: v1

kind: Service

metadata:

name: nginx

labels:

name: nginx

spec:

ports:

- name:

http

port: 80

targetPort: 80

selector:

name: nginx

version: "1.13.9"

type: LoadBalancer

kubectl apply -f bule-service.yaml

4.2.2 绿部署

创建green.yaml

apiVersion:  extensions/v1beta1

kind: Deployment

metadata:

name: nginx-1.14.1

spec:

replicas: 3

template:

metadata:

labels:

name: nginx

version: "1.14.1"

spec:

containers:

- name: nginx

image: nginx:1.14.1

ports:

- name: http

containerPort: 80

kubectl apply -f green.yaml

创建green-service.yaml

apiVersion: v1

kind: Service

metadata:

name: nginx reen-service.yaml

labels:

name: nginx

spec:

ports:

- name:

http

port: 80

targetPort: 80

selector:

name: nginx

version: "1.14.1"

type: LoadBalance

kubectl apply -f reen-service.yaml

k8s+docker集群整合搭建(完整版)相关推荐

  1. Rancher+K8S+Docker集群搭建

    Rancher+K8S+Docker集群搭建 Ubuntu安装 准备工作:准备VMware+Ubuntu(ubuntu-18.04.5-live-server-amd64.iso) 1.1 虚拟机安装 ...

  2. k8s docker集群搭建

    一.Kubernetes系列之介绍篇 1.背景介绍 云计算飞速发展 - IaaS - PaaS - SaaS Docker技术突飞猛进 - 一次构建,到处运行 - 容器的快速轻量 - 完整的生态环境 ...

  3. Hadoop之——基于3台服务器搭建Hadoop3.x集群(实测完整版)

    转载请注明出处:https://blog.csdn.net/l1028386804/article/details/93892479 一.  服务器规划 二.Hadoop集群环境的准备 搭建Hadoo ...

  4. 基于kubeadm快速部署kubernetes K8S V1.17.4集群-无坑完整版

    基于kubeadm快速部署kubernetes K8S V1.17.4集群,并部署Dashboard Web页面,实现可视化查看Kubernetes资源 主机配置规划 服务器名称(hostname) ...

  5. Kubernetes(K8S)集群部署搭建图文教程(最全)

    Kubernetes 集群安装 前期准备 集群安装 系统初始化 Harbor采取私有的仓库去镜像使用 集群检测 集群功能演示 前期准备 第一步:Router软路由构建 第二步:centos7安装 5台 ...

  6. spark集群,kafka集群和zookeeper的docker集群快速搭建

    准备操作 安装docker(宿主机) yum install docker (宿主机时centos用yum管理包) systemctl daemon-reload(重加载deamon服务,是docke ...

  7. Apache Kafka:集群的搭建和测试

    当前版本:kafka_2.12-2.8.0.CentOS7 1. 声明 当前内容主要为学习和使用Kafka搭建集群,当前内容借鉴官方文档 官方文档描述如下:要想搭建集群,就必须配置相同的zookeep ...

  8. Docker+K8S 集群环境搭建及分布式应用部署

    互联网正在飞速发展,早已由最初的单体架构演变为如今的分布式架构,而分布式架构也为系统运维带来了挑战.架构在发展,系统运维技术也在不断升级.而伴随着系统运维的是如今炒的火热的容器技术,Docker 就是 ...

  9. 学习笔记之-Kubernetes(K8S)介绍,集群环境搭建,Pod详解,Pod控制器详解,Service详解,数据存储,安全认证,DashBoard

    笔记来源于观看黑马程序员Kubernetes(K8S)教程 第一章 kubernetes介绍 应用部署方式演变 在部署应用程序的方式上,主要经历了三个时代: 传统部署:互联网早期,会直接将应用程序部署 ...

  10. k8s集群下搭建数据同步工具-canal:canal-admin篇

    k8s集群下搭建数据同步工具-canal:canal-admin篇 前言 容器化 canal-admin 环境准备 k8s集群创建pod canal-admin 前言 本文使用v1.1.4版本的can ...

最新文章

  1. 升级版APDrawing,人脸照秒变线条肖像画,细节呈现惊人
  2. swift 笔记 (十二) —— 下标
  3. JavaMelody+Spring+struts2配置详解——系统监控
  4. Spring全家桶中的日志框架
  5. php安装soap扩展
  6. Ocelot(六)- 架构图
  7. 前端学习(3345):数组方法的使用
  8. php表单提取,php – 使用RegEx提取表单字段
  9. Android开发笔记(六十八)工程库打包
  10. Google 要放弃 Android 了?
  11. 原创:软件架构那点事儿(二)
  12. 【干货】跨端体验度量的思考与实现(含直播回放)
  13. C#常用 API函数大全
  14. ERStudio如何显示entity的tableName(表名的英文)和defaultColumnName(英文字段名)
  15. 基于Vue的移动端图片裁剪组件 vue-clip(完美兼容ios与安卓)
  16. Learn Git Branching 答案
  17. 轻松完成word格式的接口文档
  18. 重叠头像最简单实现(RecyclerView实现)
  19. Building Loosely Coupled and Scalable RESTful Services using Orleans
  20. vue项目如何减少app.js和vender.js的体积

热门文章

  1. LANTENNA:通过以太网电缆泄露,从物理隔离网络中窃取数据
  2. VirusTotal智能搜索安卓样本示例
  3. 什么是 cisco ios
  4. 使用位运算求正数的相反数
  5. java 阳历日期时间获取年月日时干支
  6. python开发单片机仿真软件_开源电子电路仿真模拟软件,加油国产芯片
  7. HTML5期末大作业:个人网页设计——作家三毛6页(代码质量好) 学生DW网页设计作业源码 web课程设计网页规划与设计
  8. Windows10打印机共享无法连接到打印机:0x0000011b
  9. 广和通亮相世界宽带论坛2022,构建5G FWA全场景无线宽带体验
  10. SVN文件夹对号图标(更新、冲突等)不显示