欢迎访问我的博客,你的支持,是我最大的动力!

企业级容器集群构建(四)Kubernetes解决方案_服务/存储/任务

Docker 小马奔腾 3187℃ 评论
目录:
[显示]

《容器即服务.从零构建企业级容器集群》林帆2018.4 笔记

使用kubernetes

部署服务

服务部署主要使用Deployment和Service对象,可分别用kubelet run和kubelet expose命令来创建

# 创建deployment对象
kubectl run nginx --image=nginx
# 创建service对象
kubectl expose deployment nginx --port=80 --target-port=80 --name=nginx-svc

kubectl create和kubectl apply命令可通过yaml或json描述文件创建各种类型的资源

示例项目:https://github.com/kubernetes/examples

部署前端应用

service是将集群中需要被外部访问的pod暴露出来,本质上是使用iptables的内置负载均衡器,选择依据是pod的标签,上面需要同时有两个标签app:guestbook和tier:frontend,两个标签需要同时满足。

service对象有四种类型:
ClusterIP,默认,负载均衡会使用内网IP,只能从集群中节点访问
NodePort,除内网IP外,还会在每个Node上占用一个端口,作为服务的入口
LoadBalancer,在NodePort基础上,自动调用平台API为Node节点暴露的端口创建外部负载均衡器,仅支持AWS和GCE
ExternalName,将外部服务地址暴露到集群内,并赋予一个能通过集群DNS访问的服务名称

创建
kubectl create -f frontend-deployment.yaml
kubectl create -f frontend-service.yaml
#kubectl create -f redis-master-deployment.yaml
#kubectl create -f redis-master-service.yaml
#kubectl create -f redis-slave-deployment.yaml
#kubectl create -f redis-slave-service.yaml
## -f参数可指定一个资源描述文件,也可指定一个目录,为目录时,该目录下所有yaml/json文件都会被读取
# 查看pod
kubectl get pod
# 查看replicaset
kubectl get rs
# 查看deployment
kubectl get deploy
# 查看service
kubectl get svc   #可看到映射出来的端口,不指定会是一个30000-32767范围内的随机端口

注,上表中简写没有大写字母。并不是所有资源都有简写,如jobs、cronjobs、secrets等没有简写

kubectl describe 加资源类型和资源名称,查看特定资源实例的详细信息
kubectl describe svc frontend
kubectl delete 可删除指定资源
kubectl delete deploy frontend redis-master redis-slave
kubectl delete svc frontend redis-master redis-slave
kubectl delete -f examples/guestboot  # 快速删除目录下所有资源

服务在线更新和回滚

对服务进行在线扩容、缩容、升级、回滚

kubectl proxy --www=$(pwd)/local --port=8080 --address=0.0.0.0
## 该命令会监听本地一个端口,并将发送到此端口的请求代理到集群api上;--www参数将本地指定目录映射到代理服务的/static路径下

kubectl scale 加资源类型可缩放pod实例个数,目前可缩放的资源类型只有replicationcontroller和deployment
kubectl scale rc update-demo-nautilus --replicas=4

kube rollout (kubectl rolling-update已废除)滚动更新,即每次增加指定个数的新版本pod,然后删除相应个数的旧版本pod
kubectl rolling-update update-demo-nautilus --update-period=3s -f kitten-rc.yaml
# 每三秒一个的速度替换当前运行的pod
升级过程中可使用ctrl+c中断更新操作,执行kubectl rolling-update --rollback回滚
注,回滚只适用于在升级过程中,若已升级完成,则需要执行升级,升级到低版本
kubectl rolling-update update-demo-nautilus update-demo-kitten --rollback
## rc名称update-demo-nautilus -> update-demo-kitten

kubectl apply命令,相当于kubectl create --save-config
kubectl apply --record -f nautilus-deploy.yaml
# --record会将执行的kubectl命令内容记录下来
deployment的升级不能使用kubectl rolling-update,而应直接修改原资源文件内容,再执行kubectl apply
这个升级过程也是逐个替换pod,但不能精确控制每个pod升级过程的间隔时间
kubectl edit可以自动读取当前资源的配置内容,并使用系统命令行修改
注,可使用--record参数将操作内容记录到资源对象中
kubectl get deploy
kubectl edit --record deploy nginx
kubectl edit deployment/nginx -o yaml --save-config
编辑完成,保存即自动按更新的内容执行相应操作
kubectl rollout history可以查看指定资源的部署历史,在使用--record参数后,将包括更新命令
kubectl rollout history deploy nginx
# 只能看到一个版本??
kubectl rollout history deploy nginx --revision=1  #查看某一版本的详细信息
kubectl rollout undo 能回滚到上一个版本
kubectl rollout undo deploy nginx
并不是所有属性都可以在运行时更改,如容器对外暴露端口,添加type:NodePort属性,此时使用kubectl apply命令会出错,应该使用kubectl replace
kubectl replace --record -f nautilus-deploy.yaml
相当于相应的资源先删除然后重建

单次任务/定时任务/全局服务

job、cronjob、daemonset同样用于服务或事务的运行,基于pod进行部署

job用于执行具有确定结束条件的单次任务,通常是运算类事务或由事件触发的批处理任务。结束后会通过进程返回值告知处理结果是否成功

kubectl create -f pi.yaml
kubectl get job
kubectl get pods
kubectl logs pi-hd4gc  #可以查看计算的结果

cronjob 周期性运行

kubectl create -f cron-pi.yaml
kubectl get cronjob
另一种创建cronjob的方式,注意-- perl之间的空格
kubectl run pipi --schedule="*/30 * * * *" --restart=OnFailure --image=perl -- perl -Mbignum=bpi -wle "print bpi(10)"

daemonset 对象部署的服务会在集群中每个node上都运行一个单独的pod实例,主要用于部署基础设施服务,如监控工具、日志收集代理等
有新节点添加进集群,也会自动部署该类型的pod,保证在所有节点上有具只有一个所属pod在运行

kubectl create -f nginx-daemon.yaml
kubectl get daemonset
kubectl get pod -o wide  #可额外显示ip 节点等信息

持久化存储

docker使用的是copy-on-write特性的文件系统,其读写效率比普通的文件系统低,通过挂载volume,可以将普通目录挂载到容器里,从而获得更好的数据性能。

emptyDir类型的volume会在本地磁盘自动创建一个空目录并挂载
hostPath类型的volume则由用户指定挂载的本地目录
一个pod中可以定义多个volume,且这些volume可以被同一容器中所有容器共享

PersistentVolume资源对象,一个环境中可用的Volume资源;PersistentVolumeClaim资源对象是对资源需求的声明

kubectl create -f demo-volumes.yaml
kubectl create -f demo-claim.yaml
当一个资源(persistentvolumeclaim)声明被创建时,它会自动寻找能适配需求的最小存储资源,并绑定,这样,其他persistentvolumeclaim对象不能再绑定
# 查看绑定关系
kubectl get pv
kubectl get pvc
在创建pod时,只需将挂载类型写成persistentvolumeclaim,并指定使用的资源声明名称,就可以自动找到合适的volume并进行挂载

kubectl create -f demo-pod.yaml

配置存储

应用程序与配置信息分别管理,如配置文件、数据库地址等

ConfigMap和Secret资源对象,这些对象由管理人员创建,在服务启动时转化为普通文件形式加入目标服务的容器
ConfigMap原样存储配置信息的明文内容
Secret数据用二进制存储,所有文本需先被序列化成base64编码的字符串

ConfigMap对象

kubectl create -f db-configmap.yaml
kubectl get configmap
kubectl get configmap db-config2 -o yaml
kubectl edit configmap db-config2

由于ConfigMap存储内容通常是一些键值对或完整的properties配置文件,所以可以用 --from-literal 和 --from-file 参数简化创建
同一个ConfigMap可以包含多个配置文件,只需添加多个 --from-file 参数

cat db.properties
db.addr: 10.134.1.1
db.table: kube

kubectl create configmap db-config --from-literal=color.good=purple --from-literal=color.bad=yellow --from-file=db.properties

Secret对象

secret对象的type属性有三个值:0paque、kubernetes.io/dockerconfigjson、kubernetes.io/service-account-token
0paque,最常见,应用的普通配置信息 注意,第一个字符是数字0零不是字母O
kubernetes.io/dockerconfigjson,docker本身的配置文件,通常用于拉取一些要登录才能使用的私有仓库docker镜像,在配置文件中添加用户信息
kubernetes.io/service-account-token,让容器中程序能访问https保护的kube-apiserver服务,将通信证书token数据传送容器内部的一种volume对象
secret对象yaml中所有数据值都需使用base64编码,数据在创建时可以用键值对形式表示

kubectl create -f demo-secret.yaml
kubectl get secret
kubectl get secret db-user-pass -o yaml
kubectl describe secret db-user-pass

# 可将需存储的值以明文方式存放到以键名称命名的文本文件中
## 注意 echo -n 行尾没有换行符
echo -n "admin" >./username
echo -n "kube123" >./password
kubectl create secret generic db-user-pass --from-file=./username --from-file=./password
## 若键名与文件名不一致,可以用 --from-file=<键名称>=<文件名> 格式,如 --from-file=username=./data.txt
## 也可以用明文形式创建,使用--from-literal参数
kubectl create secret generic db-user-pass --from-literal=username=admin --from-literal=password=kube123

在Pod中使用ConfigMqp和Secret,支持使用环境变量和还原成文件两种方式为服务提供配置信息,使用configMapKeyRef和secretKeyRef参数

kubectl create -f view-env-pod.yaml
# 查看日志内容
kubectl logs view-env-pod

kubectl create -f view-folder-pod.yaml
kubectl logs view-folder-pod
# 下面是文件挂载结果
/etc/config:
color.bad
color.good
db.properties

/etc/config-secret:
password
username

用于从私有仓库拉取时docker的自动登录

kubectl create secret docker-registry dockerhub-key --docker-server=hub.docker.com --docker-username=test --docker-password=mypasswd --docker-email=admin@qq.com

有状态服务

StatefulSet有状态服务,需要稳定持久化的存储的服务。解决当服务漂移后数据不随服务转移到新节点,若是replicaset则只能让所有副本共享相同远程挂载目标的问题

StatefulSet会将每个pod副本编号,同时将所挂载的存储卷也编号,当发生漂移时,存储卷随pod迁移到新的节点上,当pod所属容器启动时,会自动找到属于自己的存储卷,重新挂载

使用StatefulSet部署高可用MySQL服务集群

创建StatefulSet前,需先准备网络存储数据卷。数据卷可由StorageClass自动添加,也可使用PersistentVolume方式预先添加到集群中

Ceph集群创建参考:分布式文件系统Ceph部署-基于CentOS7
相关命令:

创建rbd默认pool:rbd
ceph osd pool create rbd 50
创建名为demo_volume_0的数据卷
rbd create demo_volume_0 --size 10240 -m 192.168.10.110 --keyring /etc/ceph/ceph.client.admin.keyring
禁用kubernetes不需要的RDB特性(防止挂载数据卷失败)
rbd feature disable demo_volume_0 exclusive-lock object-map fast-diff deep-flatten

这里创建了demo_volume_0到demo_volume_4共5个数据卷
连接ceph集群需要密钥,先创建ceph-secret.yaml
# 获取base64后的密钥
grep key /etc/ceph/ceph.client.admin.keyring |awk '{printf "%s", $NF}'|base64

kubectl create -f ceph-secret.yaml

创建PersistentVolume对象

kubectl create -f ceph-10gb-0.yaml

创建PersistentVolumeClaim对象
注意:该对象命名规则是StatefulSet中的volumeClaimTemplates名称+StatefulSet名称+序号,命名错误会导致创建StatefulSet对象时无法找到pvc的问题

kubectl create -f ceph-10gb-0-pvc.yaml

创建ConfigMap

kubectl create -f mysql-configmap.yaml

创建Service

kubectl create -f mysql-services.yaml

创建StatefuSet

kubectl create -f mysql-statefulset.yaml

错误处理:
报错1:fail to check rbd image status with: (executable file not found in $PATH), rbd output: ()
原因:k8s的node节点需要有rbd可执行文件,因为使用了k8s中存储的密钥,所以无需关心密钥,如复制密钥文件到/etc/ceph目录
处理:
yum install yum-plugin-priorities  #ceph源中有优先级设置,需要此插件才支持优先级覆盖,否则安装的是老的ceph-common
添加ceph源
yum install ceph-common

报错2:mount: wrong fs type, bad option, bad superblock on /dev/rbd0
原因:块设备需要预先格式化为ext4
处理:
在monitor节点上操作
# 查看已创建的rbd列表
rbd list
demo_volume_0
# 将image映射为块设备
rbd map demo_volume_0
/dev/rbd0
# 格式化
mkfs.ext4 /dev/rbd0
# 从内核中unmap
rbd unmap demo_volume_0

StatefulSet创建Pod是依次有序进行的,仅当当前Pod进入就绪状态,才会开始下一个Pod的创建
有状态服务往往是区分主从身份的
kubectl get pods -l app=mysql
若某一pod意外崩溃,将在其他节点上自动重建,并自动挂载原来的pod存储卷,实现有状态服务故障漂移

StatefulSet操作
扩大
kubectl scale statefulset mysql --replicas=5
查看
kubectl get pods -l app=mysql
缩小
kubectl scale statefulset mysql --replicas=3
销毁
kubectl delete statefulset mysql
## StatefulSet被删除后,相应的存储卷和PVC并不自动销毁,所以即使StatefulSet完全删除,再次创建时,其生成的每个Pod仍然依次挂载原有的数据卷,并获得相应数据;若要释放这些资源,应显式执行删除操作,如
kubectl delete pvc -l app=mysql
kubectl delete pv ceph-10gb-0 ...
rbd rm demo_volume_0

 

转载请注明:轻风博客 » 企业级容器集群构建(四)Kubernetes解决方案_服务/存储/任务

喜欢 (0)or分享 (0)