k8s入门

今天开始学习k8s

学习k8s是一个要持续坚持很长时间的事情。

定义

k8s是一个全新的,基于容器技术的分布式架构领先方案。
Google开源。

基本知识

核心

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

  • 拥有一个唯一的指定的名字;
  • 拥有一个虚拟IP和端口号;
  • 能够提供某种远程服务能力;
  • 被映射到了提供这种能力的一组容器上;

    关于service

    service的服务进程目前都基于socket通信方式对外提供服务,或者是实现了某个具体业务的特定的tcp server进程。
    一个service通常由多个相关的服务进程来提供服务,每个服务进程都有一个独立的EndPoint,但是k8s能够让我们通过service连接到指定的service上。
    pod的关系:
    一个pod是一个服务进程的包装,一组pod组成一个servicepodservice之间的关系的建立,是由label来实现的。通过标签选择器选择。很显然,一个service对应一个标签选择器。

    关于pod

    一个pod是一组容器组成的,里面有一个特殊的pause容器,k8spause容器代表整个容器组的状态。这一组容器内的多个业务容器都共享pause容器的IP,共享pause容器挂接的volumek8s要求底层网络支持集群内任意两个pod之间的tcp/ip直接通信。因此需要牢记一点:在k8s里,一个pod里的容器与另外主机的pod容器能够直接通信。
    pod2种类型:普通pod和静态pod,后者比较特殊,不存放在etcd里,而是存放在某个具体node上的某个具体文件里,并且这个静态pod总是存在这个node上。普通的pod,一旦被创建,就会被放到etcd中存储,随后被k8s调度到某个具体的node上并进行绑定,随后该pod被对应的node上的kubelet进程实例化成一组相关的容器并启动起来。在默认情况下,pod里的某个容器如果出现死亡,整个pod就会重启,当然,整个pod里的所有容器都会被重启。

    关于资源描述

    k8s里用yamljson描述资源,下面以pod为例讲述:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    apiVersion: v1 #k8s版本
    kind: Pod #表明资源类型是一个pod
    metadata: #元数据,里面的数据最丰富
    name: mywebserver #pod的名字
    labels: #标签,用于选择,k8s选择具备这些标签node进行这个pod的创建
    name: myweb #具体的标签的内容
    spec: #一些spec设置,这是次于metadata的次丰富的一项
    containers: #描述容器
    - name: myweb 容器的名字
    image: kubeguide/tomcat-app:v1 #容器创建时使用的镜像
    ports: # 描述容器的端口
    - containerPort: 8080 #容器暴露的端口,相当于dockerfile中使用EXPOSE 8080
    env: #设置一些环境变量,容器要依赖的
    - name: MYSQL_SERVICE_HOST
    value: 'mysql'
    - name: MYSQL_SERVICE_PORT
    value: '3306'

    关于资源限额

    k8s中,通常以千分之一个CPU为一个m;内存配额也是一个绝对值,单位是内存字节数,下面是一个示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    spec:
    containers:
    - name: db
    image: db/centos
    resources: #对容器的资源进行描述
    requests:
    memory: "64Mi"
    cpu: "250m"
    limits:
    memory: "128Mi"
    cpu: "500m"

    关于标签选择

    这个标签选择涉及到一些集合,正则一类的,这里先不做深究,上面示例描述文件中可以看到label描述项,这里只来讲述下他是怎么用的。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    apiVersion: v1
    kind: Service
    metadata:
    name: webserver
    spec:
    selector:
    app: myweb
    ports:
    - port: 8080
    这里使用具有标签app:myweb的一些资源(包括pod等等)来工作。
    标签选择器的几个重要的使用场景:
  • kube-controller进程通过资源对象RC上定义的label来筛选要监控的pod的副本的数量。
  • kube-proxy通过Service描述文件中定义的标签选择器来建立对pod的路由。
  • 通过对node进行打标签,在pod中使用NodeSelector这种标签调度策略,kube-scheduler实现定向调度。

    RC(副本控制)

    简单来讲,RC定义了一个期望的场景:即声明某种pod的数量要符合一个期望值,为了实现这个目的,RC的定义包括以下几点:
  • pod期望的数量;
  • 标签选择器来监控pod
  • pod的副本数量小于期望的数量时,重新创建pod使用的模板;
    以下是一个示例描述文件:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    apiVersion: v1
    kind: RelicationController
    metadata:
    name: frontend
    spec:
    replicas: 2
    selector:
    tier: frontend
    template:
    metadata:
    labels:
    app: app-demo
    tier: frontend
    spec:
    containers:
    - name: tomcat-demo
    image: tomcat/centos
    imagePullPolicy: IfNotPresent
    env:
    - name: GET_HOTS_FROM
    value: dns
    ports:
    - containerPort: 80
    这里多讲一点,上面的格式-标示数组。也就是说,containers下面可以有多个镜像;同样地,env下面也可以有好多个,ports下面也可以有好多个。
    RC提交之后,是由master节点上的controller manager组件来使用的,他会根据这个RC描述文件进行定期巡检以保证pod满足描述文件的要求。
    另外,可以通过执行kubectl scale命令来动态修改RC实现动态扩容:
    1
    kubectl scale rc redis-slave --replicas=3
    这样就把redis-slave这个pod的副本数量改为3

下一代RC

k8sv1.2时,升级成RS,即replica set。与上一代的RC存在的唯一区别是,RS支持基于集合的标签选择,RC只支持等式。

Relica SetDeployment这个更高层的对象一起逐步替换了之前RC的作用,是k8sv1.3pod自动扩容和伸缩这个告警功能实现的基础。

关于RC的总结:

  • RC实现pod的创建过程及副本数量的自动控制;
  • RC里包含完整的pod模板;
  • RC通过标签选择器来实现对pod副本的控制;
  • 通过对数量的控制,实现pod的扩缩容;
  • 改变RC里面模板的版本信息,可以实现滚动升级;

HPA

前面讲过,可以使用kubectl scale命令来实现扩缩容,但是不够自动化,hpa的作用是设定一个指标,根据指标的变化情况实现自动扩缩容。

一个具体例子:

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
namespace: default
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
kind: Deployment
name: php-apace
targetCPUUtilizationPercentage: 90

上面这个例子是说,这个hpa控制的目标对象是由名叫php-apacheDeployment里的pod副本。

StatefulSet

之前的poddeployment等等这些资源对象都是无状态的,但是一些db类的服务是有状态的。

statefulset作为deployment/rc的一个变种,用来控制有状态的pod

特性:

  • pod具有稳定的唯一网络标识,可以用来发现集群内的其他成员。
  • pod副本的启停顺序是受控的。
  • 每个pod具有稳定的持久化存储卷,pod被删除的时候,存储卷不会被删除。

headless service配合使用。headless service与普通的service的区别在于,headless service没有cluster ip,如果解析headless service的域名,那么会返回该service对应的全部podendpoint列表。