本文采用本地k8s v1.10.3版本开发,若是尚未搭建可参照 kubernetes学习笔记 (一):搭建本地k8s开发环境进行搭建node
docker pull docker.io/registry
拉取registry的镜像到本机docker run -d -p 5000:5000 --name=registry --restart=always --privileged=true --log-driver=none -v /home/data/registrydata:/tmp/registry registry
运行刚刚拉取的registry@Get('whoami')
async whoAmI() {
debug('whoAmI called with %O', {});
return { serverType: Config.SERVER_TYPE };
}
复制代码
FROM node:8
WORKDIR /root
RUN mkdir -p /root/app
COPY package.json /root/app/
COPY dist /root/app/dist
WORKDIR /root/app
RUN npm config set registry https://registry.npm.taobao.org/ ;\
npm config set disturl https://npm.taobao.org/dist/ ;\
npm i --production
CMD [ "node", "/root/app/dist/main.js" ]
EXPOSE 80
复制代码
echo 'Building to dits ...'
tsc
echo 'Docker building image ...'
docker build --rm -t localhost:5000/gateapp:0.0.1 .
echo 'Pushing ...'
docker push localhost:5000/gateapp
echo 'Docker list images ...'
docker images
复制代码
最后你会看到localhost:5000/gateapp:0.0.1的镜像已经在你的机器中啦,下面会用到docker
apiVersion: extensions/v1beta1 # kubectl api的版本
kind: Deployment # kubernetes的资源类型
metadata:
name: gate-deployment-dev
spec:
replicas: 2 # 运行的Pod副本数量
template:
metadata:
labels:
app: gate-app-dev
spec:
containers:
- name: gateapp
image: localhost:5000/gateapp:0.0.1 # Docker镜像地址(上面建立的)
env: # 镜像启动时的环境变量
- name: NODE_ENV
value: 'development'
- name: HTTP_PORT
value: '80' # 容器http的端口 须要本身代码中实现
复制代码
经过kubectl apply -f xxx.yaml
就能够部署上面的Deployment的了,也能够打开Kubernetes的Dashboard点击建立,输入yaml文件中的内容进行建立。通过一段时间后,在Dashboard面板中能够看到,1个部署 gate-deployment-dev,一个副本集 gate-deployment-dev-775d556ffb,两个容器组 gate-deployment-dev-775d556ffb-2tlgn、gate-deployment-dev-775d556ffb-sfqrq,能够点击查看每一个资源的信息,大部份内容都是自解释的。数据库
在部署Deployment后,Kubernetes大体执行了如下几个过程:npm
此时上面的镜像提供的接口还不能供外界访问,须要建立一个对应的Servicejson
apiVersion: v1 # kubectl api的版本
kind: Service # kubernetes的资源类型
metadata:
name: gate-svc-dev
spec:
type: NodePort # service的类型 ClusterIp类型 只有Cluster内部节点和Pod能够访问 NodePort Cluster外部能够经过<NodeIp>:<NodePort>访问 LoadBalancer负载均衡
selector:
app: gate-app-dev # 与上面的template中定义的label一致
ports:
- protocol: TCP # 只有TCP 或 UDP
port: 80 # clusterIp 监听的端口
nodePort: 30000 # Node 监听的端口取值范围 30000-32767
targetPort: 80 # Pod 监听的端口
复制代码
kubectl apply -f xxx.yaml
或者在Dashboard中建立api
观察Dashboard面板,会发现多了一个名字叫gate-svc-dev的服务,提供了监听了30000端口安全
curl http://localhost:30000/whoami
能够看到接口已经能够访问了bash
须要注意的是:网络
为何须要Service?app
Deployment等其余Controller动态建立和销毁Pod来保证应用的健壮性,也就是Pod是脆弱的,应用是健壮的,咱们不应指望Pod的健壮性。每一个Pod都有本身的ClusterIp地址,当Pod发生故障被新的Pod替代时,ClusterIp颇有可能发生变化,因此若是直接让外界访问Pod就有问题了。
Service和Pod如何映射?
经过上面的yaml定义能够看出,Service经过 label标签选择器选择对应的一堆Pod。当请求被发送到Service上时,Service采用了某种分配策略把流量转发到了某一个Pod上面进行处理。
Service有哪些类型?
<NodeIp>:<NodePort>
访问Service滚动更新是一次只更新一小部分副本,成功后再更新更多的副本,最终完成全部副本的更新。滚动更新最大的好处就是零停机,保证了业务的连续性。
echo 'Building to dits ...'
tsc
echo 'Docker building image ...'
docker build --rm -t localhost:5000/gateapp:0.0.2 .
echo 'Pushing ...'
docker push localhost:5000/gateapp
echo 'Docker list images ...'
docker images
复制代码
这时候能够看到有0.0.1 和 0.0.2两个版本的镜像
在Dashboard中编辑Deployment,把image: localhost:5000/gateapp:0.0.1
改为image: localhost:5000/gateapp:0.0.2
,点击更新
等待一段时间,再观察全部的Pod都被更新成0.0.2版本的了,是否是很方便!
反复执行上面的步骤,不难发现更新过程当中Kubernets都作了什么:
自定义滚动更新行为
strategy:
rollingUpdate: # 滚动更新策略
maxSurge: 10% # 数值越大 滚动更新时新建立的副本数量越多
maxUnavailble: 10% # 数值越大 滚动更新时销毁的旧副本数量越多
replicas: 2 # 运行的Pod副本数量
复制代码
- maxSurge:此参数控制滚动更新中副本总数超过DESIRED的数量或最大比例,数值越大 滚动更新时新建立的副本数量越多
- maxUnavailble:此参数控制滚动更新中,不可用的副本占DESIRED的最大数量或最大利弊,数值越大 滚动更新时销毁的旧副本数量越多
复制代码
那若是更新过程出错了怎么办?请接着往下看
Kubernetes有很强大的自愈能力,默认的实现方式是重启发生故障的容器,此外用户可使用Liveness、 Readiness的探测机制设置更为精细的健康检查,进而真正实现零停机部署、避免部署无效的镜像、更加安全的滚动升级
image: localhost:5000/gateapp:0.0.13
readinessProbe: # 一种健康检查决定是否加入到service 对外服务
httpGet:
scheme: HTTP # 支持http https
path: /healthy
port: 80 # 与你的pod端口一致
initialDelaySeconds: 10 # 容器启动多久后开始检查
periodSecods: 5 # 几秒检查一次
复制代码
readinessProbe便是使用Readiness健康探测机制,当检查不经过时(例如接口返回的状态码不是200-400之间),Kubernetes就不会把容器添加到Service中供外界访问,观察Pod的状态为Not Ready。 initialDelaySeconds是决定容器启动多久后开始检查,一般要比启动时间再长一些;periodSecods是多久检查一次,连续3次探测失败后,Ready将变成不可用,Kubernets把这个Pod从Service中下线
LiveNess的配置项和Readiness的同样,不一样之处在于探测失败后的行为。前者会重启容器,后者会设置Pod不可用,并从Service中下线。
LiveNess和Readiness的探测是独立使用的,两者没有依赖,能够单独使用也能够同时使用。通常状况下使用LiveNess判断容器是否须要重启实现自愈;Readiness判断容器是否已经准备好对外提供服务。
@Get('healthy')
async checkHealthy(@Res() res: Response) {
let isHealthy = false;
// some code to check healthy begin
isHealthy = true;
// check end
const data = {
isHealthy,
};
debug('执行健康检查结果 %O', data);
res.status(isHealthy ? HttpStatus.OK : HttpStatus.INTERNAL_SERVER_ERROR).json(data);
}
复制代码
相信看完以上的文章,你也会认为Kubernetes真的很是强大,是很是值得学习的。笔者也是小白一个,从0开始学习的,若是你也想一块儿,能够加入咱们的群。