kubernetes从入门到放弃1--(墙内安装+资源概念)

断断续续玩儿Kubernetes也快两个月了吧,毕竟是事实上的“容器编排之王”,k8s的知识点还真不是一般的多,还是决定要开个坑总结和梳理下Kubernetes有关的知识。网上Kubernetes的各种讲解也很多了,所以我就只是大概梳理下结构,能给链接的地方就直接帖外链了。
大概分为以下几个部分:

  • 墙内安装
  • 资源概念
  • 组件架构
  • 网络原理
  • 安全机制
  • 存储原理

一 墙内安装

要学习Kubernetes首先得搭一个集群起来。按照官方文档,很多组件都是要去墙外下载的,甚至用到的容器也是托管在google的服务器上。天朝自有国情在,即使有梯子,安装速度可能也很感人。我在尝试了一堆安装工具后,找到了两个可以用,并且可以学习安装过程的教程。

  • https://github.com/liverpoolpjy/follow-me-install-kubernetes-cluster

    挺详细的安装教程,但是对于萌新来说,一步一步跟着复制粘贴可能都不知道在干嘛,反而容易操作失误。而且安装的是1.6版本,有些过于陈旧。

  • https://github.com/gjmzj/kubeasz

    这个应该是墙内最好的自动化安装脚本了,紧跟最新版本,使用ansible避免了操作多台主机的麻烦,如果正确设置了hosts文件,基本是一键就安装好了。更重要的是作者给出了每一步安装的比较详细的说明,可以比较清晰的看懂整个流程。这里deploy-note是我记录的一些方便安装的tips。

二 资源概念

Kubernetes的作用是编排和管理一个集群中的众多容器,Kubernetes抽象和封装出了很多的资源概念,使得容器的编排和管理变得轻松。

2.1 Pods

Pods是Kubernetes最小的管理单位,它由一个或者多个紧密相关的容器组成,这些容器共享同一个网络栈。因此在同一个Pod中的容器可以用localhost+port的形式访问到pod中的其他容器。另外,同一个Pod中的容器还可以共享Pod级的存储卷Volume。可以发现,Pod的定义是为了方便一些功能上密切相关的容器相互通信。

2.1.1 pause container

每个Pod中,都有一个叫做pause的容器,用来管理整个Pod。pause容器有两个作用:

  1. Pod中的所有容器需要共享IP和Volume,那怎么管理这些IP和Volume呢?不如使用一个和业务无关的容器,让它的IP和Volume为Pod中的容器所共享,这样只需要监管pause容器,就可以管理整个Pod的IP和Volume了。
  2. Pod中可能有多个容器,怎么确定一个Pod的状态呢?于是又使用一个和业务无关的pause容器,以它的状态表示整个Pod的状态。

2.2 Controllers

一些服务是由一个Pod中的众多容器组成,出于可用性考虑可能需要为它创建一些副本集。Controller就是用来管理这些副本集的。

2.2.1 Replication Controller -> Replica Set

这两个Controller的主要作用是控制Pod副本集的数量,分为两个方面:

  • 保证集群中的副本集数量保持在期望水平。如果某些Pods挂掉了,Controller会自动生成相同数量的新Pod,使副本集的数量保持不变。
  • 管理副本集数。主要是通过命令kubectl scale --replicas=2 rs/<rs-name>执行。

这两个Controller都是通过Pod上的Label对Pod选择,从而进行精细化的控制。然而Replication Controller只能基于等式选择,而Replica Set可以用基于集合的选择器。

...
spec:
   replicas: 3
   selector:
     matchExpressions:
      - {key: teir, operator: NotIn, values: [production]}
...

2.2.2 Deployment

Deployment是一个更高阶的控制器,他通过控制Replica Set而间接控制Pods副本集。它比起前面两个Controller的升级在于可以实时监控Pods副本集创建后的状态。因为Pods副本集从创建,调度到某个Node,到拉去镜像运行需要一段时间,所以这种监控也是需要的。创建一个Deployment看一看:

# redis-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: redis
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      tier: backend
  template:
    metadata:
      labels:
        app: redis
        tier: backend
    spec:
      containers:
      - name: redis
        image: redis
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 6379
root@kube-1:~# kubectl create -f redis-deployment.yaml
root@kube-1:~# kubectl get deployment
NAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
redis      2         2         2            2           32s

这里就可以通过上述输出达到监控Pods副本集的目的。再来看看通过Deployment创建的Replica Set和Pod:

root@kube-1:~# kubectl get rs
NAME                  DESIRED   CURRENT   READY     AGE
redis-7f464bcbbb      2         2         2         1m
root@kube-1:~# kubectl get pods
NAME                        READY     STATUS    RESTARTS   AGE
redis-7f464bcbbb-nfxln      1/1       Running   0          1m
redis-7f464bcbbb-rkm8f      1/1       Running   0          1m

需要注意的是Replica Set是由Deployment创建,Pod是由Replica Set创建。他们把管理的权限都让渡给了Deployment。这时如果执行扩容命令:kubectl scale --replicas=4 rs/redis-7f464bcbbb,是无效的。必须要用Deployment执行:

kubectl scale --replicas=4 deployment/redis

从这里可以看出Deployment、Replica Set、Pod的关系:

root@kube-1:~# kubectl describe rs redis-7f464bcbbb | grep 'Controlled By'
Controlled By:  Deployment/redis
root@kube-1:~# kubectl describe pod redis-7f464bcbbb-nfxln | grep 'Controlled By'
Controlled By:  ReplicaSet/redis-7f464bcbbb

实际使用中,基本都是通过这三个资源实例来管理集群中的Pod副本集。
更详细的关于Pod、Replica Set、Deployment的内容可以参考:Kubernetes Replication Controller, Replica Set and Deployments: Understanding replication options
另一方面,默认情况下Pod是由Kubernetes调度到Node上运行,但具体是哪一个Node,还需要通过Label选定。Kubernetes还定义了一些特定场景下使用的Controller。

2.2.3 DeamonSet

通过DeamonSet管理的Pod副本集会在每一个Node上运行一个Pod。这种设定非常适合于日志采集、性能监控等服务。
比如我们安装集群的工具kubeasz就是通过DeamonSet方式部署flannel网络组件的: https://github.com/gjmzj/kubeasz/blob/master/docs/07-安装flannel网络组件.md

2.2.4 StatefulSet

有状态副本集。通常用来管理存储相关的服务。因为它管理的Pod名称、运行位置、IP等都不会随意改变。还没有实际使用过……

2.2.5 Job、CronJob

相当于控制Pod执行批处理任务或者定时任务,处理完任务就结束。

2.3 Service

Kubernetes通过Controller保证了提供服务的能力和服务的质量。但是Pod副本集是动态的,随时可以扩容缩容、产生毁灭……要访问到Pod副本集提供的服务,就需要监控起Pod随时的变化,然后把对服务的请求转发到某一个Pod上。上述的就正是Service的主要作用——定义服务的访问入口。

#redis-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: default
spec:
  type: ClusterIP
  ports:
  - port: 6379
  selector:
    tier: backend
kubectl create -f redis-service.yaml

这样就为redis这个Deployment定义了一个服务入口,如果使用kubectl就相当于:

root@kube-1:~# kubectl expose deployment redis --port=6379

查看下service的详细信息:

root@kube-1:~# kubectl describe service redis
Name:              redis
Namespace:         default
Labels:            app=redis
                   tier=backend
Annotations:       <none>
Selector:          tier=backend
Type:              ClusterIP
IP:                10.68.8.207
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         172.20.1.10:6379,172.20.2.7:6379
Session Affinity:  None
Events:            <none>

简单扯下Kubernetes的三种网络和三种IP:

这时在集群内访问Service的ClusterIP+Port:10.68.8.207:6379,就可以访问到redis服务了。有了Service,就可以不用关心一个Deployment的很多信息:它有多少个副本,分别在哪里,有没有新生成的副本......只需要一个记住ClusterIP+Port,就可以访问到服务。
由于ClusterIP是一个虚拟的IP地址,所以仅限于集群内可以访问。如果要从集群外访问到服务,那么还需要做一些微小的工作。可以看看第三篇中关于service外部访问部分的内容。

三 Summary

以上的Pod、Controller、Service就从:容器管理、副本集管理和服务对外入口三个方面基本构成了一个容器集群的主要功能。这些在我看来也就是Kubernetes最主要的资源概念了。
然而,当你输入kubectl get就可以发现,Kubernetes的资源概念多达30多个。一些是和安全机制或者存储机制有关的以后再总结,另外一些就是基本没用过的,用到再说咯...

Comments
Write a Comment