一 应用场景描述
持续跟踪研究Kubernetes也有一段时间了,Kubernetes作为谷歌开源的生产级别的容器调度系统从开源初始便获得了众多的关注。一些有研发实力的公司调研过Kubernetes的设计理念以及应用场景后很快就组织研发人员结合Kubernetes开发出符合自身业务发展的容器管理平台,也有一些公司基于Kubernetes开发公有容器云平台对外提供服务。但是对于一些小型团队对Kubernetes还是保持观望态度并适当做些测试。对比与mesos,kubernetes目前缺少一个像DC/OS这样一个完整的容器管理平台。手动部署过Kubernetes的朋友一定有所感触,Kubernetes手动部署真是相当麻烦。使用kubeadm可以快速部署kubernetes集群,但是官方不建议在生产环境使用。如果想快速方便的部署一套生产环境的kubernetes集群并有用类似DC/OS的功能,rancher是个不错的选择。
rancher是一个完整的开源容器管理平台,它可以部署并管理mesos、docker swarm、kubernetes和rancher自己的开发的编排工具cattle。本文结合rancher来了解kubernetes的基础知识。
二 通过rancher部署kubernetes集群
1.部署rancher
本文使用以下版本:
docker版本: 1.12.6
OS版本: CentOS7.3
rancher支持的OS内核版本和docker版本参考链接http://rancher.com/docs/rancher/v1.6/en/hosts/#supported-docker-versions
rancher server有两个不同的tags,
rancher/server:latest 这个tag是最新的开发版本,不适用于生产环境
rancher/server:stable 这个tag是最新的稳定版本,建议用于生产环境.
# sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server:stable
# sudo docker logs -f
在浏览器访问 http://172.30.30.215:8080
出现以下界面。
2.部署kubernetes集群
点击Managed Environments , 选择 Add Environment , 然后填上Name 和 Description
Environment template 选择Kubernetes,最后点击Create
点击INFRASTRUCTURE 选择Hosts然后点击Add Host , 将显示的命令在准备用来做rancher 节点的服务器上执行即可。
rancher使用kubernetes原生的dashboard
点击>_CLI 可以在rancher界面操作kubernetes命令,点击Generate Config生产config文件,将这个文件复制到rancher节点的 ~/.kube/config文件,就可以在rancher节点使用kubernetes命令了
rancher有个好用的功能就是可以直接在rancher界面进入容器查看或者操作,点击INFRASTRUCTURE然后选择Containers,找到想要查看的容器,点击Execute Shell
三 kubernetes基础知识
1.创建kubernetes集群
前面已经通过rancher创建了一个kubernetes集群
master 负责管理集群
node 负责运行应用并通过api与master通信
# kubectl version
# kubectl cluster-info
# kubectl get nodes
2. 部署一个应用
deployment负责创建和更新应用实例。
#kubectl run kubernetes-bootcamp --image=docker.io/jocatalin/kubernetes-bootcamp:v1 --port=8080
kubectl run 创建一个deployment
--image 指定docker镜像
--port 指定应用端口
查看deployments
# kubectl get deployments
默认情况下,部署的应用只对kubernetes集群内部可见
可以通过以下两种方法查看:
# kubectl proxy
Starting to serve on 127.0.0.1:8001
打开另一个终端
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
kubernetes-bootcamp-390780338-7db2d 1/1 Running 0 17m 10.42.5.102 ceph-osd219
# curl http://localhost:8001/api/v1/proxy/namespaces/default/pods/kubernetes-bootcamp-390780338-7db2d
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-390780338-7db2d | v=1
或者直接通过pod的IP访问
# curl http://10.42.5.102:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-390780338-7db2d | v=1
3.查看pods和nodes
一个Pod就是一个kubernetes抽象,它代表一组一个或者多个应用容器和这些容器共享的资源。
这些资源包括:
共享存储,volumes
网络,唯一的集群IP
如何运行每个容器的相关信息,例如容器镜像版本或者使用的指定端口
pods是kubernetes的原子单元,也就是最小的单元。
当我们创建一个deployment时,deployment会创建一些包含容器的pods,而不是直接创建容器。
每个pod会附着在它被调度到的node上,直到被终结或者被删除。在node不可用的情况下,相同的pods会被调度到集群中其他可用的nodes上
Nodes
一个pod总是运行在一个node上。一个node就是kubernetes中的一个工作机器,可以是虚拟机也可以是物理机。每个node都被master管理。
常用的kubectl命令
kubectl get - 列出资源
kubectl describe - 展示一个资源的详细信息
kubectl logs - 打印一个pod中的一个容器的日志
kubectl exec - 在一个pod中的一个容器上执行命令
4. 使用service暴露应用
pods是有生命周期的。当一个工作节点死掉后,这个节点上的运行的pods也随之丢失。一个replicationcontroller 通过创建新的pods来保持应用运行可能动态地驱使集群恢复到该有的状态。
一个service就是一个kubernetes中的抽象层,它定义了一套pods和一个访问这些pods的策略。
尽管每个pod都有一个唯一的IP地址,但是这些IP地址如果不通过service是无法暴露到集群外部的。
service允许应用可以接收外部流量。service可以通过指定type类型以不同的方式暴露:
ClusterIP(默认) 暴露service到集群内部的IP上。只能在集群内部可达。
NodePort 通过NAT方式暴露service到每个选定的集群node的相同端口上。这是ClusterIP的超集。
LoadBalancer 在当前云上创建一个外部负载均衡器并指派一个固定的、外部IP到这个service上。这是NodePort的超集。
ExternalName 使用一个任意名字来暴露这个service,返回一条包含这个名字的CNAME。不需要用到proxy。这种类型需要kube-dns版本在v1.7或者以上。
一个service在一套pods间路由流量。services是一个允许pods在kubernetes中死掉和复制而不影响应用的抽象层。
services使用labels和selectors匹配一套pods
kubectl expose 可以创建一个service
# kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service "kubernetes-bootcamp" exposed
# kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.43.0.1 443/TCP 5h
kubernetes-bootcamp 10.43.107.231 8080:31194/TCP 13s
# kubectl describe services/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: run=kubernetes-bootcamp
Selector: run=kubernetes-bootcamp
Type: NodePort
IP: 10.43.107.231
Port: 8080/TCP
NodePort: 31194/TCP
Endpoints: 10.42.5.102:8080
Session Affinity: None
No events.
可以看出在每个node上暴露了一个31194端口
# curl 172.30.30.219:31194
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-390780338-7db2d | v=1
通过这个端口可以成功访问应用
可以使用labels来过滤pods,services,deployment
# kubectl get pods -l run=kubernetes-bootcamp
# kubectl get services -l run=kubernetes-bootcamp
# kubectl get deployment -l run=kubernetes-bootcamp
使用kubectl label命令重新给pod加label
# kubectl label pod kubernetes-bootcamp-390780338-7db2d app=v1
# kubectl get pods -l app=v1
使用kubectl delete删除service
# kubectl delete service -l run=kubernetes-bootcamp
再查看service,发现之前创建的service已经被删除了
# kubectl get services
再访问node的端口已经无法访问了
# curl 172.30.30.219:31194
curl: (7) Failed connect to 172.30.30.219:31194; Connection refused
这就证明这个应用不能在集群外部访问了。再确认下这个应用是否仍然运行
# kubectl exec -it kubernetes-bootcamp-390780338-7db2d curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-390780338-7db2d | v=1
5.扩展应用实例
在之前的例子中,只部署了一个应用实例,当流量增加时就需要扩展应用实例。扩展实例是通过更改deployment中的replicas数量来完成。
scale up确保新的pods会被创建并被调度到有可用资源的节点上。scale down将减少pods数量到期望的状态。kubernetes还支持自动扩容pods,以后再讨论。
使用 kubectl scale来扩容pods
# kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment "kubernetes-bootcamp" scaled
# kubectl get pods -o wide
# kubectl describe deployments/kubernetes-bootcamp
再使用kubectl expose来创建一个service暴露端口
# kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
查看暴露的nodeport
# kubectl get services/kubernetes-bootcamp
然后执行
# curl 172.30.30.219:30403
可以看到有不同的pod交替显示,这就证明service有路由流量和负载均衡的功能
再将应用实例减少到2个
# kubectl scale deployments/kubernetes-bootcamp --replicas=2
deployment "kubernetes-bootcamp" scaled
再查看deployment和pod的状态,确认应用只能下2个实例了。
6.执行rolling updates操作
用户期望应用每时可用,开发者期望一天可以多次部署新版本。在kubernetes,这种需求通过rolling updates完成。rolling updates允许deployment更新操作可以零宕机。
使用kubectl set image命令更新应用镜像版本
# kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment "kubernetes-bootcamp" image updated
查看pod的镜像版本
# kubectl describe pods
发现Image一行已经更换成jocatalin/kubernetes-bootcamp:v2
更新也可以通过rollout status确认
# kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out
回滚更新
再执行另一次更新,部署镜像tag v10
# kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v10
再查看pods和deployments的状态,tag为v10的镜像不存在。更新失败!需要执行rollback操作回滚到之前的版本
# kubectl rollout undo deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" rolled back
再查看pods和deployments的状态恢复正常,pods的Image版本为之前的v2
参考文档:
https://dcos.io/
https://www.openshift.org/
http://rancher.com/rancher/
http://rancher.com/docs/rancher/v1.6/en/
https://kubernetes.io/docs/tutorials/kubernetes-basics/