今天开始学习k8s。
学习k8s是一个要持续坚持很长时间的事情。
定义
k8s是一个全新的,基于容器技术的分布式架构领先方案。
由Google开源。
基本知识
核心
k8s中,service是分布式集群架构的核心,一个service对象拥有如下关键特征:
- 拥有一个唯一的指定的名字;
- 拥有一个虚拟
IP和端口号; - 能够提供某种远程服务能力;
- 被映射到了提供这种能力的一组容器上;
关于
serviceservice的服务进程目前都基于socket通信方式对外提供服务,或者是实现了某个具体业务的特定的tcp server进程。
一个service通常由多个相关的服务进程来提供服务,每个服务进程都有一个独立的EndPoint,但是k8s能够让我们通过service连接到指定的service上。
与pod的关系:
一个pod是一个服务进程的包装,一组pod组成一个service。pod和service之间的关系的建立,是由label来实现的。通过标签选择器选择。很显然,一个service对应一个标签选择器。关于
一个podpod是一组容器组成的,里面有一个特殊的pause容器,k8s用pause容器代表整个容器组的状态。这一组容器内的多个业务容器都共享pause容器的IP,共享pause容器挂接的volume。k8s要求底层网络支持集群内任意两个pod之间的tcp/ip直接通信。因此需要牢记一点:在k8s里,一个pod里的容器与另外主机的pod容器能够直接通信。pod有2种类型:普通pod和静态pod,后者比较特殊,不存放在etcd里,而是存放在某个具体node上的某个具体文件里,并且这个静态pod总是存在这个node上。普通的pod,一旦被创建,就会被放到etcd中存储,随后被k8s调度到某个具体的node上并进行绑定,随后该pod被对应的node上的kubelet进程实例化成一组相关的容器并启动起来。在默认情况下,pod里的某个容器如果出现死亡,整个pod就会重启,当然,整个pod里的所有容器都会被重启。关于资源描述
k8s里用yaml和json描述资源,下面以pod为例讲述:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17apiVersion: 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
11spec:
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
9apiVersion: v1
kind: Service
metadata:
name: webserver
spec:
selector:
app: myweb
ports:
- port: 8080app: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
23apiVersion: 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 Set和Deployment这个更高层的对象一起逐步替换了之前RC的作用,是k8sv1.3里pod自动扩容和伸缩这个告警功能实现的基础。
关于RC的总结:
RC实现pod的创建过程及副本数量的自动控制;RC里包含完整的pod模板;RC通过标签选择器来实现对pod副本的控制;- 通过对数量的控制,实现
pod的扩缩容; - 改变
RC里面模板的版本信息,可以实现滚动升级;
HPA
前面讲过,可以使用kubectl scale命令来实现扩缩容,但是不够自动化,hpa的作用是设定一个指标,根据指标的变化情况实现自动扩缩容。
一个具体例子:
1 | apiVersion: autoscaling/v1 |
上面这个例子是说,这个hpa控制的目标对象是由名叫php-apache的Deployment里的pod副本。
StatefulSet
之前的pod,deployment等等这些资源对象都是无状态的,但是一些db类的服务是有状态的。
statefulset作为deployment/rc的一个变种,用来控制有状态的pod。
特性:
pod具有稳定的唯一网络标识,可以用来发现集群内的其他成员。pod副本的启停顺序是受控的。- 每个
pod具有稳定的持久化存储卷,pod被删除的时候,存储卷不会被删除。
与headless service配合使用。headless service与普通的service的区别在于,headless service没有cluster ip,如果解析headless service的域名,那么会返回该service对应的全部pod的endpoint列表。