kubernetes 容器编排系统

前言

docker解决了打包和隔离的问题,但是在docker集群中我们需要解决更多的问题,如调度(容器在哪运行)、生命周期及健康状况(确保容器在无错的情况下运行)、服务发现(容器所处位置,和容器通信)、监控(容器运行是否正常)、认证(谁能访问我的容器)、容器聚合(如何将多个关联的容器聚合一个工程),在集群中需要解决这么问题,但是docker并没有给出解决方案,kubenetes就是解决这些问题的。

kubernetes概述及使用

轻量级、简单,可以在公有云、私有云及混合云部署,模块化(mudular),可插拔化(pluggable)- 可以使第三方的用户很容易将自己的应用集成到kubenetesz中,可挂接(hookbale)-可以接收kubernetes产生的事件并做相应的处理,,可组合(composable)-你可以任意的选择kuberntes当中的一些功能,来组成一个完整的系统,自动恢复、自动重启、自动复制。

1、使用与kubernetes进行交互的命令接口kubernetes-kubernetes CLI

(1)在主节点查看所有的node节点

[root@k8s-master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 6d5h v1.15.2
k8s-node1 Ready <none> 6d5h v1.15.2
k8s-node2 Ready <none> 6d5h v1.15.2

(2) 获取kubernetes集群发生的事件

kubectl get events

image.png
(3)Pods

创建、调度、及管理的最小单元,共存的一组容器集合,容器共享PID-容器共享了PID命名空间,它使同一个Pods内的容器可以看到彼此的进程,网络-共享了网络命名空间,可以使同一个Pods内的容器使用相同的ip地址及其端口,通过localhost来相互访问,IPC-同一个Pods内的容器可以使用systemvip或porstem的消息队列的方式来进行通信,UTS命名空间-同一个Pods内的容器使用了相同的主机名,同时同一个Pods中的容器还可以共享存储卷-kubernetes的设计,为了更好的资源共享及容器间的通信便于管理,短暂存在-就像我们的容器一样,Pods是一个短暂存在的对象,Pods的生命周期主要分为以下几个状态:

1、首先是一个pending的状态,它表示Pods已经被系统接受,但是一个或多个容器镜像还没有创建,这包括容器在被调度之前的时间以及下载镜像的时间
2、running它表示Pods已经被部署到一个节点上,并且所有的容器镜像都被创建了
3、successed表示Pods中的容器都被成功的停止了,并且不会被重启
4、failed,它表示Pods中的所有容器都被停止了,并且至少有一个容器在停止的时候出现了错误

2、k8s最佳实践

1、创建一个基本的Pod,kubectl create –f pod.yaml
apiVersion: v1
kind: Pod  #表示yaml文件定义了一个pod对象,首字母需要大写
metadata: #表示这个对象需要的一些属性值
   name: nginx
spec:
   containers:
   - name: nginx
     image: nginx
     ports:
     - containerPort: 80


2、获取集群的Pods,kubectl get pods
[root@k8s-master opt]# kubectl get pods nginx
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          20s
3、删除pod,kubectl delete pods podsName
[root@k8s-master opt]# kubectl delete pods nginx
pod "nginx" deleted
4、上面演示了一个创建pod的案例,并在pod中运行一个nginx的容器,我们知道容器中的文件是短暂存在的,当容器crash的时候,数据将会丢失,下面使用Volumes进行pod数据持久化

Volumes的作用及生命周期:

1、数据持久化
2、Pod中容器共享数据
3、生命周期(Volumes的周期和Pod定义的生命周期是一样的),当一个Pods停止退出的时候Volumes也会停止退出,目前kubernetes支持的数据卷类型-emptyDir,hostpath,gcePersistentDisk,awsElasticBlockStore,nfs,iscsi,glusterfs,secrets

存储卷创建的几种方式

1、本地主机上创建的两种类型数据卷

1、emptyDir:当Pods被调度到一个节点的时候生成,只要Pods运行到当前节点上便一直存在,其初始是一个空文件夹,Pods内的容器可以读取此文件夹中的文件,当此Pods从此节点删除的时候,数据卷也会被相应的删除,我们需要注意容器crash的时候,数据卷是不会被删除的
2、hostpath:可以指明当前宿主机上的一个路径映射到我的Pods内

2、云端存储

gcePersistentDisk,awsElasticBlockStore

3、网络存储

nfs,iscsi,glusterfs

4、加密存储secrets

用于存储比较敏感的数据,如果用户密码

创建一个包含Volumes的Pods,kubectl create -f volumes.yaml

apiVersion: v1
kind: Pod
metadata:
   name: redis
spec:
   containers:
   - name: redis
     image: redis
     volumeMounts:
     - name: redis-persistent-storage
       mountPath: /data/redis
   volumes:
   - name: redis-persistent-storage
     emptyDir: {}
使用yaml格式查看redis Pod的详细信息,kubectl get pods redis -o yaml
image.png


Label的作用

用以表示对象(如Pod)的key/value对,组织并选择对象子集,Labels使用户可以使用松耦合的方式来映射自己应用的组织结构,而不需要存储这些映射表,那么与命名和uid不同的是,Label不需要提供唯一性,反而我们希望多个对象使用相同的Label,通过Label选择器用户可以指定一些对象子集来进行分组合并。
创建一个Labels的pod,kubectl create -f label.yaml
apiVersion: v1
kind: Pod
metadata:
    name: nginx
    labels:
      app: nginx
spec:
   containers:
   - name: nginx
     image: nginx
     ports: 
     - containerPort: 80
查看带有label的Pod,kubectl get pods -l app=nginx-web
image.png

这个时候我们已经可以创建一个带labels并能够提供持久化的pod,但是当我们的节点出错或者需要维护的时候,我们如何确保我们的Pods能被调度到其他节点正常运行呢?在kubernets当中有一个replication controller的概念,我们简称它为RC

RC的概述

1、保证在任意时刻运行指定数量的Pod,比如说我要指定刚才创建的nginx在任意时候都要运行一个Pod,当我运行nginx的pod的节点出现错误时,那么我的这个RC确保这个Pod会被调度到另外可以工作正常的接点上,保证Pod正常运行
2、容器重新调度,可以把它当做守护进程,与之不同的是RC监控的事多个节点的多个Pod
3、规模调度,它使规模调度变得简单,你只需要修改指定Pod的数目,RC便会删除多余的容器和启动新的容器以达到指定的数目
4、在线升级,同时RC可以通过一个接一个替换Pod的方法实现在线升级,你可以增加一个新版本的Pod,然后删除一个旧的Pod,之后当旧版本的Pod数目为0的时候,你可以删除旧的RC,需要注意的是我们使用新版本的Pod和旧版本Pod的RC需要至少有一处不同label以标记不同版本的RC
5、多发布版本跟踪,在某一个时间段内运行多个版本的应用是可能的,这个多个版本的追踪也是可以通过设置不同的label,通过RC去实现
创建一个rc,kubectl create -f rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3 #创建nginx pod实例的数量
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

查看rc的信息,kubectl get rc,并查看创建的Pod
image.png
尝试删除其中一个Pod,验证RC是否重新创建一个,kubectl delete pods podName,可以看到重新创建了一个Pod,rc控制器始终保证了Pod的运行数量
image.png


每个Pods都有自己的ip地址,并且这些地址并不是固定的,这带来一个问题,如果一些Pods是被另外一些Pods提供服务的,那么它如何被发现呢,kubernetes为此提供了service的抽象去解决这个问题

Service的定义

1、抽象一系列Pod并定义访问规则
2、它为每一个服务提供了一个固定的虚拟的ip和dns域名
3、我们可以通过环境变量和DNS的方式发现服务
4、同时它还提供了非常简单的负载均衡
5、它定义了我们Pod的访问方式,目前有三种,首先是一个ClusterIP(它只能在当前集群内访问),type是NodePort的时候,那么它是使用了ClusterIP,同时它还会在集群的每一个节点上暴露一个服务的端口,你可以通过这个集群的某一个工作节点的ip地址以及这个端口来访问这个服务,如果你的云服务商提供支持外部负载均衡的话,那么你可以使用LoadBalancer这个类型,通过service的访问你并不需要Pods的ip,service的ip是一个固定的ip,并且你可以通过kubernetes提供的DNS服务进行查询
创建一个service,kubectl create -f service.yaml
apiVersion: v1
kind: Service
metadata:
   name: nginx-service
spec:
  ports:
  - port: 8000 # The port that this service should serve on the container on each pod to connect to,
               #can be a name(eg,'www') or a number(eg,'80')
    targetPort: 80
    protocol: TCP
               #            # Just like the selector in the replication controller,but this time it identifies the set of pods load balance traffic to.
  selector:
        app: nginx
查看service的状态,kubectl get service
image.png
在节点上验证service暴露是否成功,cutrl http://ClusterIP:port
image.png
原文地址:https://www.cnblogs.com/lcword/p/14540685.html