K8S入门实战

274 阅读20分钟

Kubernetes大纲:

image.png

第一章:Kubernetes介绍

k8s组件

kubernetes组件

一个kubernetes集群主要是由控制节点(master)、**工作节点(node)**构成,每个节点上都会安装不同的组件。

master:集群的控制平面,负责集群的决策 ( 管理 )

ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制

Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上

ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等

**Etcd **:负责存储集群中各种资源对象的信息

**node:集群的数据平面,负责为容器提供运行环境 ( 干活 ) **

Kubelet : 负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器

KubeProxy : 负责提供集群内部的服务发现和负载均衡

Docker : 负责节点上容器的各种操作

image.png

kubernetes概念

Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控

Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的docker负责容器的运行

Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器

Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等

Service:pod对外服务的统一入口,下面可以维护者同一类的多个pod

Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签

NameSpace:命名空间,用来隔离pod的运行环境,同个命名空间下的pod可以互相访问,不同命名空间下的是不能狐仙访问的。

image.png

第二章;集群环境搭建

环境规划

集群类型

kubernetes集群大体上分为两类:一主多从多主多从

  • 一主多从:一台Master节点和多台Node节点,搭建简单,但是有单机故障风险,适合用于测试环境
  • 多主多从:多台Master节点和多台Node节点,搭建麻烦,安全性高,适合用于生产环境

image.png

说明:为了测试简单,本次搭建的是 一主两从 类型的集群

安装方式

kubernetes有多种部署方式,目前主流的方式有kubeadm、minikube、二进制包

  • minikube:一个用于快速搭建单节点kubernetes的工具
  • kubeadm:一个用于快速搭建kubernetes集群的工具
  • 二进制包 :从官网下载每个组件的二进制包,依次去安装,此方式对于理解kubernetes组件更加有效

说明:现在需要安装kubernetes的集群环境,但是又不想过于麻烦,所以选择使用kubeadm方式

主机规划

作用IP地址操作系统配置
Master192.168.109.101Centos7.5 基础设施服务器2颗CPU 2G内存 50G硬盘
Node1192.168.109.102Centos7.5 基础设施服务器2颗CPU 2G内存 50G硬盘
Node2192.168.109.103Centos7.5 基础设施服务器2颗CPU 2G内存 50G硬盘

环境搭建

本次环境搭建需要安装三台Centos服务器(一主二从),然后在每台服务器中分别安装docker(18.06.3),kubeadm(1.17.4)、kubelet(1.17.4)、kubectl(1.17.4)程序。

  • 主机安装
  • 环境初始化
  • 安装docker
  • 安装k8s组件
  • 准备集群镜像
  • 集群初始化
  • 安装网络插件

第三章:资源管理

资源管理介绍

在kubernetes中,所有的内容都抽象为资源,用户需要通过操作资源来管理kubernetes。

​ kubernetes的本质上就是一个集群系统,用户可以在集群中部署各种服务,所谓的部署服务,其实就是在kubernetes集群中运行一个个的容器,并将指定的程序跑在容器中。

​ kubernetes的最小管理单元是pod而不是容器,所以只能将容器放在Pod中,而kubernetes一般也不会直接管理Pod,而是通过Pod控制器来管理Pod的。

​ Pod可以提供服务之后,就要考虑如何访问Pod中服务,kubernetes提供了Service资源实现这个功能。

​ 当然,如果Pod中程序的数据需要持久化,kubernetes还提供了各种存储系统。

image.png

学习kubernetes的核心,就是学习如何对集群上的Pod、Pod控制器、Service、存储等各种资源进行操作

yaml语言

YAML的语法比较简单,主要有下面几个:

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不允许使用tab,只允许空格( 低版本限制 )
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • '#'表示注释

YAML支持以下几种数据类型:

  • 纯量:单个的、不可再分的值
  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hash) / 字典(dictionary)
  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
# 纯量, 就是指的一个简单的值,字符串、布尔值、整数、浮点数、Null、时间、日期
# 1 布尔类型
c1: true (或者True)
# 2 整型
c2: 234
# 3 浮点型
c3: 3.14
# 4 null类型 
c4: ~  # 使用~表示null
# 5 日期类型
c5: 2018-02-17    # 日期必须使用ISO 8601格式,即yyyy-MM-dd
# 6 时间类型
c6: 2018-02-17T15:02:31+08:00  # 时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
# 7 字符串类型
c7: heima     # 简单写法,直接写值 , 如果字符串中间有特殊字符,必须使用双引号或者单引号包裹 
c8: line1
    line2     # 字符串过多的情况可以拆成多行,每一行会被转化成一个空格

小提示:
1 书写yaml切记: 后面要加一个空格
2 如果需要将多段yaml配置放在一个文件中,中间要使用---分隔
3 下面是一个yaml转json的网站,可以通过它验证yaml是否书写正确
www.json2yaml.com/convert-yam…

命令式对象管理

kubectl命令

kubectl是kubernetes集群的命令行工具,通过它能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署。kubectl命令的语法如下:

kubectl [command] [type] [name] [flags]

comand:指定要对资源执行的操作,例如create、get、delete

type:指定资源类型,比如deployment、pod、service

name:指定资源的名称,名称大小写敏感

flags:指定额外的可选参数

# 查看所有pod
kubectl get pod 
​
# 查看某个pod
kubectl get pod pod_name
​
# 查看某个pod,以yaml格式展示结果
kubectl get pod pod_name -o yaml

资源类型

kubernetes中所有的内容都抽象为资源,可以通过下面的命令进行查看:

kubectl api-resources

经常使用的资源有下面这些:

资源分类资源名称缩写资源作用
集群级别资源nodesno集群组成部分
namespacesns隔离Pod
pod资源podspo装载容器
pod资源控制器replicationcontrollersrc控制pod资源
replicasetsrs控制pod资源
deploymentsdeploy控制pod资源
daemonsetsds控制pod资源
jobs控制pod资源
cronjobscj控制pod资源
horizontalpodautoscalershpa控制pod资源
statefulsetssts控制pod资源
服务发现资源servicessvc统一pod对外接口
ingressing统一pod对外接口
存储资源volumeattachments存储
persistentvolumespv存储
persistentvolumeclaimspvc存储
配置资源configmapscm配置
secrets配置

操作

命令式对象配置

image.png 总结: 命令式对象配置的方式操作资源,可以简单的认为:命令 + yaml配置文件(里面是命令需要的各种参数)

声明式对象配置

kubectl apply -f nginxpod.yaml 仅用于创建和更新。

资源控制小结

image.png

第四章:实战入门

namespace

  • 不同的namespace给不同的租户,实现了不同namespace下的资源隔离。采用了多租户的设置,通过k8s的资源配置机制,给不同的租户分配不同的资源大小。
  • 命名空间的创建、删除。
  • kubectl create ns dev
  • kubectl delete ns dev

pod

  • 一个pod可以放多个容器 image.png
  • 程序在容器中,容器在pod中,k8s通过控制pod控制容器。
  • pod中有根容器+用户容器。
  • 创建:实际上创建的是pod控制器
  • 删除:删除pod控制器,则pod就死亡了;不能单纯的删除pod,因为pod控制器会再 创建一个pod实例。
  • 采用yaml创建\删除容器。

Label:标签

Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识,用来对它们进行区分和选择。

Label的特点:

  • 一个Label会以key/value键值对的形式附加到各种对象上,如Node、Pod、Service等等
  • 一个资源对象可以定义任意数量的Label ,同一个Label也可以被添加到任意数量的资源对象上去
  • Label通常在资源对象定义时确定,当然也可以在对象创建后动态添加或者删除

可以通过Label实现资源的多维度分组,以便灵活、方便地进行资源分配、调度、配置、部署等管理工作。

一些常用的Label 示例如下:

  • 版本标签:"version":"release", "version":"stable"......
  • 环境标签:"environment":"dev","environment":"test","environment":"pro"
  • 架构标签:"tier":"frontend","tier":"backend"

标签定义完毕之后,还要考虑到标签的选择,这就要使用到Label Selector,即:

Label用于给某个资源对象定义标识

Label Selector用于查询和筛选拥有某些标签的资源对象

Deployment :pod控制器

  • k8s中pod控制器很多,本章节只介绍一种:Deployment
  • 使用命令|yaml进行增删改查
  • kubectl create -f deploy-nginx.yaml

Service

  • pod被删除后,由pod控制器创建生成新的pod,且新pod的ip也会被变更,那程序对外如何暴露服务?
  • 由Service对外暴露访问的IP,根据负载均衡算法找到一个pod执行。 image.png 通过上节课的学习,已经能够利用Deployment来创建一组Pod来提供具有高可用性的服务。

虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:

  • Pod IP 会随着Pod的重建产生变化
  • Pod IP 仅仅是集群内可见的虚拟IP,外部无法访问

这样对于访问这个服务带来了难度。因此,kubernetes设计了Service来解决这个问题。

Service可以看作是一组同类Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。

image.png

操作一:创建集群内部可访问的Service service类型:ClusterIp 操作二:创建集群外部部可访问的Service service类型:NodePort

上面创建的Service的type类型为ClusterIP,这个ip地址只用集群内部可访问 如果需要创建外部也可以访问的Service,需要修改type为NodePort.
[root@master ~]# kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n dev service/svc-nginx2 exposed

第五章:Pod课程

在kubernetes中基本所有资源的一级属性都是一样的,主要包含5部分:

  • apiVersion 版本,由kubernetes内部定义,版本号必须可以用 kubectl api-versions 查询到
  • kind 类型,由kubernetes内部定义,版本号必须可以用 kubectl api-resources 查询到
  • metadata 元数据,主要是资源标识和说明,常用的有name、namespace、labels等
  • spec 描述,这是配置中最重要的一部分,里面是对各种资源配置的详细描述
  • status 状态信息,里面的内容不需要定义,由kubernetes自动生成

    在上面的属性中,spec是接下来研究的重点,继续看下它的常见子属性:

    • containers <[]Object> 容器列表,用于定义容器的详细信息

    • nodeName 根据nodeName的值将pod调度到指定的Node节点上

    • nodeSelector <map[]> 根据NodeSelector中定义的信息选择将该Pod调度到包含这些label的Node 上

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

    • volumes <[]Object> 存储卷,用于定义Pod上面挂在的存储信息

    • restartPolicy 重启策略,表示Pod在遇到故障的时候的处理策略

    • kubectl explain pod

    • kubectl explain pod.kind

    pod配置

    本小节主要来研究pod.spec.containers属性,这也是pod配置中最为关键的一项配置。

        [root@master ~]# kubectl explain pod.spec.containers
    KIND:     Pod
    VERSION:  v1
    RESOURCE: containers <[]Object>   # 数组,代表可以有多个容器
    FIELDS:
       name  <string>     # 容器名称
       image <string>     # 容器需要的镜像地址
       imagePullPolicy  <string> # 镜像拉取策略 
       command  <[]string> # 容器的启动命令列表,如不指定,使用打包时使用的启动命令
       args     <[]string> # 容器的启动命令需要的参数列表
       env      <[]Object> # 容器环境变量的配置
       ports    <[]Object>     # 容器需要暴露的端口号列表
       resources <Object>      # 资源限制和资源请求的设置
    

    第六章:Pod 控制器

    ## Pod控制器介绍
    

    Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类:

    • 自主式pod:kubernetes直接创建出来的Pod,这种pod删除后就没有了,也不会重建
    • 控制器创建的pod:kubernetes通过控制器创建的pod,这种pod删除了之后还会自动重建

    什么是Pod控制器

    Pod控制器是管理pod的中间层,使用Pod控制器之后,只需要告诉Pod控制器,想要多少个什么样的Pod就可以了,它会创建出满足条件的Pod并确保每一个Pod资源处于用户期望的目标状态。如果Pod资源在运行中出现故障,它会基于指定策略重新编排Pod。

    在kubernetes中,有很多类型的pod控制器,每种都有自己的适合的场景,常见的有下面这些:

    • ReplicationController:比较原始的pod控制器,已经被废弃,由ReplicaSet替代
    • ReplicaSet:保证副本数量一直维持在期望值,并支持pod数量扩缩容,镜像版本升级
    • Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本.
    • Horizontal Pod Autoscaler:可以根据集群负载自动水平调整Pod的数量,实现削峰填谷
    • DaemonSet:在集群中的指定Node上运行且仅运行一个副本,一般用于守护进程类的任务
    • Job:它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务
    • Cronjob:它创建的Pod负责周期性任务控制,不需要持续后台运行
    • StatefulSet:管理有状态应用

    第七章:Service详解

    - service用于四层路由的负载,Ingress用于七层路由的负载。
    

    Service介绍及使用

    在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。
    

    为了解决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod进行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。

    image.png Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则

    image.png kube-proxy目前支持三种工作模式:

    userspace 模式

    image.png iptables 模式

    image.png ipvs 模式

    image.png ipvs模式和iptables类似,kube-proxy监控Pod的变化并创建相应的ipvs规则。ipvs相对iptables转发效率更高。除此以外,ipvs支持更多的LB算法。

    Service类型

    Service的资源清单文件:

    kind: Service  # 资源类型
    apiVersion: v1  # 资源版本
    metadata: # 元数据
      name: service # 资源名称
      namespace: dev # 命名空间
    spec: # 描述
      selector: # 标签选择器,用于确定当前service代理哪些pod
        app: nginx
      type: # Service类型,指定service的访问方式
      clusterIP:  # 虚拟服务的ip地址
      sessionAffinity: # session亲和性,支持ClientIP、None两个选项
      ports: # 端口信息
        - protocol: TCP 
          port: 3017  # service端口
          targetPort: 5003 # pod端口
          nodePort: 31122 # 主机端口
    
    • ClusterIP:默认值,它是Kubernetes系统自动分配的虚拟IP,只能在集群内部访问
    • NodePort:将Service通过指定的Node上的端口暴露给外部,通过此方法,就可以在集群外部访问服务
    • LoadBalancer:使用外接负载均衡器完成到服务的负载分发,注意此模式需要外部云环境支持
    • ExternalName: 把集群外部的服务引入集群内部,直接使用

    ClusterIp

    **Endpoint**
    

    Endpoint是kubernetes中的一个资源对象,存储在etcd中,用来记录一个service对应的所有pod的访问地址,它是根据service配置文件中selector描述产生的。

    一个Service由一组Pod组成,这些Pod通过Endpoints暴露出来,Endpoints是实现实际服务的端点集合。换句话说,service和pod之间的联系是通过endpoints实现的。

    image.png 负载分发策略

    对Service的访问被分发到了后端的Pod上去,目前kubernetes提供了两种负载分发策略:

    • 如果不定义,默认使用kube-proxy的策略,比如随机、轮询

    • 基于客户端地址的会话保持模式,即来自同一个客户端发起的所有请求都会转发到固定的一个Pod上

      此模式可以使在spec中添加sessionAffinity:ClientIP选项

    NodePort类型的Service

    在之前的样例中,创建的Service的ip地址只有集群内部才可以访问,如果希望将Service暴露给集群外部使用,那么就要使用到另外一种类型的Service,称为NodePort类型。NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service了。

    image.png

    创建service-nodeport.yaml

    apiVersion: v1
    kind: Service
    metadata:
     name: service-nodeport
     namespace: dev
    spec:
     selector:
       app: nginx-pod
     type: NodePort # service类型
     ports:
     - port: 80 #service的端口号
       nodePort: 30002 # 指定绑定的node的端口(默认的取值范围是:30000-32767), 如果不指定,会默认分配,物理主机的端口号。
       targetPort: 80  # 对应到pod容器的端口号
    

    Ingress配置

    在前面课程中已经提到,Service对集群之外暴露服务的主要方式有两种:NotePort和LoadBalancer,但是这两种方式,都有一定的缺点:
    
    • NodePort方式的缺点是会占用很多集群机器的端口,那么当集群服务变多的时候,这个缺点就愈发明显
    • LB方式的缺点是每个service需要一个LB,浪费、麻烦,并且需要kubernetes之外设备的支持

    基于这种现状,kubernetes提供了Ingress资源对象,Ingress只需要一个NodePort或者一个LB就可以满足暴露多个Service的需求。工作机制大致如下图表示:

    image.png

    实际上,Ingress相当于一个7层的负载均衡器,是kubernetes对反向代理的一个抽象,它的工作原理类似于Nginx,可以理解成在**Ingress里建立诸多映射规则,Ingress Controller通过监听这些配置规则并转化成Nginx的反向代理配置 , 然后对外部提供服务**。在这里有两个核心概念:
    
    • ingress:kubernetes中的一个对象,作用是定义请求如何转发到service的规则
    • ingress controller:具体实现反向代理及负载均衡的程序,对ingress定义的规则进行解析,根据配置的规则来实现请求转发,实现方式有很多,比如Nginx, Contour, Haproxy等等

    Ingress(以Nginx为例)的工作原理如下:

    1. 用户编写Ingress规则,说明哪个域名对应kubernetes集群中的哪个Service
    2. Ingress控制器动态感知Ingress服务规则的变化,然后生成一段对应的Nginx反向代理配置
    3. Ingress控制器会将生成的Nginx配置写入到一个运行着的Nginx服务中,并动态更新
    4. 到此为止,其实真正在工作的就是一个Nginx了,内部配置了用户定义的请求转发规则

    image.png

    第八章:数据存储

    在前面已经提到,容器的生命周期可能很短,会被频繁地创建和销毁。那么容器在销毁时,保存在容器中的数据也会被清除。这种结果对用户来说,在某些情况下是不乐意看到的。为了持久化保存容器的数据,kubernetes引入了Volume的概念。

    Volume是Pod中能够被多个容器访问的共享目录,它被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录下,kubernetes通过Volume实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储。Volume的生命容器不与Pod中单个容器的生命周期相关,当容器终止或者重启时,Volume中的数据也不会丢失。

    kubernetes的Volume支持多种类型,比较常见的有下面几个:

    • 简单存储:EmptyDir、HostPath、NFS
    • 高级存储:PV、PVC
    • 配置存储:ConfigMap、Secret

    EmptyDir

    EmptyDir是最基础的Volume类型,一个EmptyDir就是Host上的一个空目录,用于Pod中多个容器共享数据,pod死亡,则EmptyDir存储也丢失。
    

    image.png

    HostPath

    解决节点故障问题:
    

    上节课提到,EmptyDir中数据不会被持久化,它会随着Pod的结束而销毁,如果想简单的将数据持久化到主机中,可以选择HostPath。

    HostPath就是将Node主机中一个实际目录挂在到Pod中,以供容器使用,这样的设计就可以保证Pod销毁了,但是数据依据可以存在于Node主机上

    image.png

    NFS

    HostPath可以解决数据持久化的问题,但是一旦Node节点故障了,Pod如果转移到了别的节点,又会出现问题了,此时需要准备单独的网络存储系统,比较常用的用NFS、CIFS

    NFS是一个网络文件存储系统,可以搭建一台NFS服务器,然后将Pod中的存储直接连接到NFS系统上,这样的话,无论Pod在节点上怎么转移,只要Node跟NFS的对接没问题,数据就可以成功访问。

    image.png

    PV与PVC

    帮助K8S的用户与管理者屏蔽掉不同存储的差异,统一存储接口。

    image.png

    第九章:安全认证

    第十章:进阶

    附录

    第1章:概述

    • 1,我们项目中k8s集群是几台服务器搭建的呢?测试环境的呢?有什么技术可以将2台物理机虚拟化为3个Node么?

    第6章:pod控制器

    • 1个pod允许使用多种控制器么?如果不允许则副本管理?版本回退这两个功能都需要,则功能是几个控制器运行呢?
      答:Deployment:通过控制ReplicaSet来控制Pod,并支持滚动升级、回退版本.

    第8章:存储

    1,configMap存储卷的内容是存储在哪个位置?保证哪个级别的数据安全性?pod死亡后数据存在?node死亡后数据存在?