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 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 ##查看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
如无特殊说明,文章均为本站原创,转载请注明出处
本文永久链接地址:https://www.xionghaier.cn/archives/976.html
该文章由
这货来去如风,什么鬼都没留下!!!