Kubernetes之Docker到CaaS集群部署

1.Kubernetes概述

Kubernetes解决的问题:调度、生命周期及健康状况、服务发现、监控、认证、容器聚合

  • 开源docker容器编排系统
  • 轻量级,简单
  • 公有云,私有云及混合云中进行部署
  • 模块化(modular),可插拔化(pluggable),可挂接(hookable),可组合(composable)
  • 自动重启,自动恢复,自动复制

2.Kubernetes语法说明

##定义Pod的语法
[root@linux-node1 docker]# vim pod.yaml
apiVersion: v1    ##使用api的版本号是v1
kind: Pod         ##yaml文件定义的对象是Pod
metadata:         ##表明了这个对象所需要的一些属性值,比如说命名为nginx
  name: nginx     
spec:             ##定义容器
  containers:
  - name: nginx   ##容器名称
    image: nginx  ##镜像名称
    ports:        ##端口
    - containerPort: 80
 [root@linux-node1 /server/docker]# kubectl get pods nginx
NAME      READY     STATUS    RESTARTS   AGE
nginx     1/1       Running   0          1m
 [root@linux-node1 /server/docker]# kubectl delete pods nginx  ###删除容器
pod "nginx" deleted

##定义volumes的语法
数据持久化,Pod中容器共享数据,生命周期,支持多种类型的数据卷(emptyDir,hostpath,gcePersistentDisk,awsElasticBlockStore,
nfs,iscsi,glusterfs,secrets)
 [root@linux-node1 /server/docker]# vim volumes.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  comtainers:
  - name: redis
    image: redis
    volumeMounts:                       ##容器当中对存储卷的定义
    - name: redis-persistent-storage    ##与下面存储卷命名是一样的,表明了使用redis-persistent-storage这个存储卷
      mountPath: /data/redis            ##挂载的路径
  volumes:                              ##定义存储卷
  - name: redis-persistent-storage      ##命名为redis-persistent-storage
    emptyDir: {}                        ##使用了emptyDir数据类型,在Pods被创建的时候会产生一个空的文件夹并且把它映射到容器中
 [root@linux-node1 /server/docker]# kubectl create -f volumes.yaml 
pod "redis" created
##查看更详细的内容
 [root@linux-node1 /server/docker]# kubectl get pods redis -o yaml   ##指定输出为yaml

##定义labels的语法
用以标示对象(如Pod)的Key/value对,组织并选择对象子集
 [root@linux-node1 /server/docker]# vim labels.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:                  ##声明了它的label是app(key值)/nginx(value)
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
 [root@linux-node1 /server/docker]# kubectl create -f labels.yaml 
pod "nginx" created
 [root@linux-node1 /server/docker]# kubectl get pods -l app=nginx    ##显示label为nginx的容器
NAME         READY     STATUS    RESTARTS   AGE
nginx        1/1       Running   0          1m

2.1创建带label并提供数据持久化的Pods

并保证节点进行维护的时候pods调度到其它节点

Replication Controllers(RC):确保任意时刻运行指定数目的Pod;容器重新调度;规模调整(修改指定的数目RC便会删除多余的容器,或启动新的容器达到指定的数目;在线升级;多发布版本跟踪)

1.创建Replication Controllers

 [root@linux-node1 /server/docker]# vim rc.yaml
apiVersion: v1                  ##使用了api版本的v1
kind: ReplicationController     ##对象的类型是ReplicationController                                                     
metadata:
  name: nginx-controller        ##metadata给它的一个命名nginx-controller
spec:                           ##在spec当中是定义了ReplicationController它需要在任何时刻确保有2个nginx pod运行
  replicas: 2
  # selector identifies the set of Pods that this
  # replication controller is responsible for managing
  selector:     ##如何去判断指定的nginx-controller,它需要一个label去做一个子集,这时候认为是监控范围的Pods
    app: nginx
  # podTemplate defines the 'cookie cutter' used for creating
  # new pods when necessary
  template:                     ##是一个Pods的定义
    metadata:
      labels:                   ##运行的pods必须有一个label
        # Important: these labels need to match the selector above
        # The api server enforces this constraint.
        app: nginx
    spec:                       ##定义pods一样定义container
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

创建ReplicationController  

 [root@linux-node1 /server/docker]# kubectl create -f rc.yaml 
replicationcontroller "nginx-controller" created

 [root@linux-node1 /server/docker]# kubectl get rc
NAME               DESIRED   CURRENT   READY     AGE
nginx-controller   2         2         1         1m

 [root@linux-node1 /server/docker]# kubectl get pods -l app=nginx
NAME                                READY     STATUS    RESTARTS   AGE
nginx                               1/1       Running   0          55m
nginx-controller-lrsvn              1/1       Running   0          3m

 [root@linux-node1 /server/docker]# kubectl delete pods nginx
pod "nginx" deleted
 [root@linux-node1 /server/docker]# kubectl get pods -l app=nginx
NAME                                READY     STATUS    RESTARTS   AGE
nginx-controller-lrsvn              1/1       Running   0          5m
nginx-controller-mwnh9              1/1       Running   0          21s

2.2Service服务介绍

我们每一个Pods都有自己的IP,而这些地址并不是固定的,那么这就会带来一些问题,一些Pods是为另外一些Pods提供服务的,那么它该如何被发现呢,我们的Kubernetes提供了Service的概念

  • 抽象一系列Pod并定义其访问规则
  • 固定IP地址和DNS域名
  • 通过环境变量和DNS发现服务
  • 负载均衡
  • 外部服务 – ClusterIP, NodePort, LoadBalancer
 [root@linux-node1 /server/docker]# vim service.yaml
apiVersion: v1                   ##版本是v1
kind: Service                    ##类型是Service
metadata:
  name: nginx-service            ##给它一个命名nginx-service
spec:                            ##在spec当中定义了ports
  ports:
  - port: 8000 # the port that this service should serve on   ##宿主机服务监听在8000端口
    # the container on each pod to connect to, can be a name
    # (e.g. 'www') or a number (e.g. 80)
    targetPort: 80                                            ##容器中80端口
    protocol: TCP                                             ##协议为tcp
  # just like the selector in the replication controller,
  # but this time it identifies the set of pods to load balance
  # traffic to.
  selector:                                                   ##为那些pods提供服务
    app: nginx

进行创建

 [root@linux-node1 /server/docker]# kubectl create -f service.yaml 
service "nginx-service" created
##查看
 [root@linux-node1 /server/docker]# kubectl get service
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
nginx-service   ClusterIP   10.1.5.161   <none>        8000/TCP   52s
##切换到工作节点去访问service
 [root@linux-node2 ~]# curl -I http://10.1.141.18:8000
HTTP/1.1 200 OK
Server: nginx/1.15.9
Date: Fri, 01 Feb 2019 05:31:42 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 26 Feb 2019 14:13:39 GMT
Connection: keep-alive
ETag: "5c754993-264"
Accept-Ranges: bytes

3.Kubernetes最佳实践

  • 数据持久化 - volumes
  • 保密数据管理 – secrets
  • 资源管理 – resources
  • 健康检测 – liveness/readiness probes
  • 生命周期钩子函数和退出警告

2.1保密数据管理

 ##准备用户及密码
 [root@linux-node1 /server/docker]# echo -n 'admin' | base64
YWRtaW4=
 [root@linux-node1 /server/docker]# echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm
##密码解析
 [root@linux-node1 /server/docker]# echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
1f2d1e2e67df
[root@linux-node1 /server/docker]# vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque                ##指定Secret类似为Opaque表示一个随机的用户数据
data:
  password: YWRtaW4=
  username: MWYyZDFlMmU2N2Rm
###创建一个secret对象
 [root@linux-node1 /server/docker]# kubectl create -f secret.yaml 
secret "mysecret" created
##进行查看
 [root@linux-node1 /server/docker]# kubectl get secret
NAME                  TYPE                                  DATA      AGE
default-token-z8mmt   kubernetes.io/service-account-token   3         22h
mysecret              Opaque                                2         1m
###如何在运用当中使用创建的逻辑卷
 [root@linux-node1 /server/docker]# vim secret-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: redis
spec:
  template:
    metadata:
      labels:
        app: redis
        tier: backend
    spec:
      volumes:                 ##挂载了两种数据卷一种是emptyDir,一种是secret
      - name: data
        emptyDir: {}
      - name: supersecret
        secret:
          secretName: mysecret ##使用了命名为mysecret这个逻辑卷,以文件的形式映射到redis容器中
      containers:
      - name: redis
        image: kubernetes/redis:v1
        ports:
        - containerPort: 6379
        # Mount the volume into the pod
        volumeMounts:
        - mountPath: /redis-master-data
          name: data # must match the name of the volume,above
        - mountPath: /var/run/secrets/super
          name: supersecret

2.2资源管理

Kubernetes的调度器只会将容器调度到有足够CPU和内存供其运行的节点上,我们可以通过指定resource来指定Pod所需的最大资源数;比较推荐的做法就是把我们的每一个对象设置成所使用的一个资源限制,这就保证了集群当中不会因为某一个应用对资源的过度应用而影响其它服务,设置资源限制的时候它也可能带来一些负面的影响,比如说,我们将CPU设置的非常小,那么就可能会导致在同一个工作节点上部署了过多的工作应用,是我们这个应用没法得到足够的CPU,同样对内存的限制也是如此

  [root@linux-node1 /server/docker]# vim resource.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: my-nginx
spec:
  replicas: 2
  template:
    matadata:
      app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        resources:
          limits:
            # cpu units are cores
            cpu: 500m
            # memory units are bytes
            memory: 64Mi

健康监测-liveness/readiness probes

没法保证我们的运用程序始终运行正常,如何检查到我们的运用程序发生错误,并且重启这个容器,Kubernetes提供了Liveness/readiness的监测

 [root@linux-node1 /server/docker]# vim liveness.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: my-nginx
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        images: nginx
        ports:
        - containerPort: 80
        livenessProbe:
          httpGet:       ##通过httpget这个命令每隔三十秒向服务去发一个index.html的主页的一个请求,返回错误将会重启
            # path to probe; should be cheap, but repersentative of typical behavior
            path: /index.html
            port: 80
          initialDelaySeconds: 30
          timeoutSeconds: 1

生命周期钩子函数和退出警告

在工作节点和应用失败退出的时候,我们希望我们的应用以一种安全干净的方式退出,例如结束正在运行的请求或者将内存当中的数据写到硬盘当中去,Kubernetes会发送SIGTERM给应用使其正常退出,如果应用在10s后还没有退出会发送SIGTERM的信号,Kubernetes支持在发送cgetem使调用用户定义的钩子函数进行相应的处理,下面定义如何使用钩子

 [root@linux-node1 /server/docker]# vim lifehook.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: my-nginx
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        lifecycle:
          preStop:          ##在Kubernetes发送SIGTERM之前退出nginx
            exec:
              # SIGTERM triggers a quick exit; gracefully terminate instead
              command: ["/usr/sbin/nginx","-s","quit"]

组织资源配置

许多应用需要创建多个资源,如一个ReplicationControoller,一个Service,管理多个资源可以简单的把它们合并到同一个文件当中,并且使用Kubernetes规定的分隔符进行分割,多个资源可以和单个资源一样按照配置文件中定义的顺序被创建,建议是把同一个资源相关的应用放在同一个配置当中,跟次相关的应用放在同一个目录底下,以便以管理,kubectl支持批量处理,

  • 组织资源配置
  • kubectl批量处理
  • 有效的利用label
  • 在线应用升级及回退
  • 实时更新资源
kubectl run inspector \
 --labels="app=inspector,track=stable" \
 --image=b.gcr.io/kuar/inspector:1.0.0

命令说明:通过kubectl run这个命令直接创建一个命名为inspector的ReplicationController,他的label为app=inspector,track表示稳定版本,镜像inspector1.0版本

 [root@linux-node1 ~]# kubectl get deployment
NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AG
inspector   1         1         1            0           59s
 [root@linux-node1 ~]# kubectl get pods
NAME                         READY     STATUS             RESTARTS   AGE
inspector-666fddf59b-8785n   0/1       ImagePullBackOff   0          2m
###通过kubectl scale deployment/rc这个命令可以动态的去调整这个运行的pod的数目
 [root@linux-node1 ~]# kubectl scale deployment inspector --replicas=5
###为这五个应用创建一个service
 [root@linux-node1 ~]# vim upgrade.yaml
apiVersion: v1
kind: Service
metadata:
  name: inspector
  labels:
    app: inspector
spec:
  type: NodePort          ##定义了NodePort表明会在每个工作节点上为它分配一个端口
  selector:
    app: inspector
    ports:
    - name: http         ##指定了是一个http的端口
      nodePort: 32000    ##它的端口是32000
      port: 80
      protocol: TCP

###命令说明
kubectl describe pod           ##查看详细信息
kubectl logs pod <container>   ##查看log
kubectl exec container command ##运行中的容器执行操作

下面部署一个GestBook应用的案例:它是由一个php server充当了我们前台的一个服务器,后端使用了redis做存储,redis包括了redis master和redis slave,它们之间是实时同步我们存储的数据,master提供了读和写的功能,slave只提供了读的操作,在我们不同的服务之间是提供了DNS来作为服务发现的

 [root@linux-node1 /server/docker]# vim redis-master-controller.yaml
apiVersion: v1
# apiVersion: apps/v1
kind: ReplicationController
# kind: Deployment
metadata:
  name: redis-master
  labels:
    name: redis-master
spec:
  replicas: 1
  selector:
  # matchLabels:
    name: redis-master
  template:
    metadata:
      labels:
        name: redis-master
    spec:
      containers:
      - name: master
        image: redis
        ports:
        - containerPort: 6379

 [root@linux-node1 /server/docker]# kubectl create -f redis-master-controller.yaml 
replicationcontroller "redis-master" created

创建service服务

 [root@linux-node1 /server/docker]# vim redis-master-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis-master
  labels:
    name: redis-master
spec:
  ports:
     # the port that this service should serve on
   - port: 6379
     targetPort: 6379
  selector:
    name: redis-master
~ 
 [root@linux-node1 /server/docker]# kubectl create -f redis-master-service.yaml 
service "redis-master" created

创建redis-slave Controller

 [root@linux-node1 /server/docker]# vim redis-slave-controller.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: redis-slave
  labels:
    name: redis-slave
spec:
  replicas: 2                                 ##指定运行2个Pods
  selector:
    name: redis-slave
  template:
    metadata:
      labels:
        name: redis-slave
    spec:
      containers:
      - name: worker
        image: kubernetes/redis-slave:v2    ##这个镜像的特殊之处是通过redis-master这个域名去访问master做DNS解析 
        ports:
        - containerPort: 6379
 [root@linux-node1 /server/docker]# kubectl create -f redis-slave-controller.yaml 
replicationcontroller "redis-slave" created
 [root@linux-node1 /server/docker]# kubectl get pods
NAME                         READY     STATUS              RESTARTS   AGE
redis-master-5wsvk           1/1       Running             0          58m
redis-slave-7tv2g            0/1       ContainerCreating   0          6s
redis-slave-hpt8x            0/1       ContainerCreating   0          6s

为redis-slave创建一个service

 [root@linux-node1 /server/docker]# vim redis-slave-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis-slave
  labels:
    name: redis-slave
spec:
  ports:
    # the port that this service should server on
  - port: 6379
  selector:
    name: redis-slave

 [root@linux-node1 /server/docker]# kubectl create -f redis-slave-service.yaml 
service "redis-slave" created
 [root@linux-node1 /server/docker]# kubectl get services

创建PHP的server

 [root@linux-node1 /server/docker]# vim frontend-controller.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend
  labels:
    name: frontend
spec:
  replicas: 3
  selector:                   ##指定选择器名字必须是frontend
    name: frontend
  template:                   ##模板说明
    metadata:
      labels:
        name: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_containers/example-guestbook-php-redis:v3  ##通过redis master/slave域名去访问
        ports:
        - containerPort: 80

创建一个Servic这个Service它会去做负载均衡,分发到我们这三个Pods中,frontend它连接了后端的redis-maste,每次访问之后可以看到guestbook的留言是可以做持久化的

 [root@linux-node1 /server/docker]# vim frontend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    name: frontend
spec:
  type: NodePort       ##因为它需要提供外部的访问,在这里我们定义的是type=NodePort这样就会在每个工作节点上去创建一个端口,可以根据工作节点的端口和IP去访问我们的服务
  ports:
    - port: 80
  selector:
    name: frontend

4.Kubernetes模块介绍

Kubernetes是由主从的分布式的集群的架构,其中分为管理节点及工作节点,管理节点是由以下几个模块组成的:
  APIServer:负责与外界的通讯,如使用kubectl的rest命令将我们对kubernetes当中系统对象的一些操作发送到我们的APIServer,那么,
同时,它还有一个scheduler的调度器及控制器的manage,我们在Kubernetes当中的所有的对象持久化到一个我们的一个分布式的key/value
的一个存储当中(etch)
  我们的真正的容器是运行在我们的工作节点上的,我们的工作节点上面有一个kubelet它会定期的与我们的ApiServe进行通讯,去吧我们当前
分配到工作节点的容器运行到当前的工作节点上,同时还有一个kube-proxy,是为我们的容器提供一个网络的代理
etcd:
  1.高可用的Key/Value存储
  2.只有apiserver有读写权限
  3.使用etcd集群确保数据可靠性
apiserver:
  1.Kubernetes系统入口, REST
  2.认证
  3.授权
  4.访问控制
  5.服务帐号:(当pods里面的进行想访问ApiServer)
  6.资源限制
kube-scheduler:
  1.资源需求
  2.服务需求
  3.硬件/软件/策略限制
  4.关联性和非关联性
  5.数据本地化
kube-controller-manager:
  1.Replication controller
  2.Endpoint controller
  3.Namespace controller
  4.Serviceaccount controller
kubelet:
  1.节点管理器
  2.确保调度到本节点的Pod的运行和健康
kube-proxy:
  1.Pod网络代理
  2.TCP/UDP请求转发
  3.负载均衡(Round Robin)
服务发现:
  1.环境变量
  2.DNS – kube2sky, etcd,skydns

 

0
如无特殊说明,文章均为本站原创,转载请注明出处

该文章由 发布

这货来去如风,什么鬼都没留下!!!
发表我的评论

Hi,请填写昵称和邮箱!

取消评论
代码 贴图 加粗 链接 删除线 签到