这里我们以简单的NodeJS应用为例,总结一下K8s如何部署应用服务。
Docker打包NodeJS应用
将自己的NodeJS应用打包到Docker中有很多种方法,大家可以参考官方文档:
https://nodejs.org/zh-cn/docs/guides/nodejs-docker-webapp/
下面介绍用最简单的方法打包自己的应用,假设我们有个应用agent_server
,我们的目录结构如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
DXHJ200-142:/home/bmc/dockerdemo # ll
total 8
-rw-r--r-- 1 root root 453 May 10 17:18 Dockerfile
drwxr-xr-x 9 root root 4096 May 10 15:59 agent_server
DXHJ200-142:/home/bmc/dockerdemo #
DXHJ200-142:/home/bmc/dockerdemo # ll agent_server/
total 52
drwxr-xr-x 4 root root 4096 May 10 14:05 .svn
-rw-r--r-- 1 root root 4350 May 10 14:05 apn_agent.js
drwxr-xr-x 2 root root 4096 May 10 19:34 config
drwxr-xr-x 2 root root 4096 May 10 14:05 libs
-rw-r--r-- 1 root root 1547 May 10 14:05 mail_agent.js
-rw-r--r-- 1 root root 36 May 10 14:32 node.web.log
drwxr-xr-x 7 root root 4096 May 10 14:05 node_modules
drwxr-xr-x 3 root root 4096 May 10 14:08 node_share
drwxr-xr-x 2 root root 4096 May 10 14:05 script
drwxr-xr-x 2 root root 4096 May 10 14:05 server
-rw-r--r-- 1 root root 6468 May 10 14:05 web_agent.js
|
上面的Dockerfile内容很简单:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# Version 1.0
# Base images 基础镜像
FROM 10.10.xxx.xxx:5000/ctos83.nodejs.14.16
# MAINTAINER 维护者信息
MAINTAINER chende
# ENV 设置环境变量
# ENV PATH /usr/local/nginx/sbin:$PATH
# ADD 文件放在当前目录下,拷过去会自动解压
COPY agent_server /home/node/
# EXPOSE 映射端口
EXPOSE 3008
WORKDIR /home/node
# CMD 运行以下命令
CMD ["node", "web_agent.js"]
|
当前目录中运行下面的目录生成相应的Docker镜像:
1
2
3
4
5
6
|
# 打包镜像
docker build -t bmcagent:111 .
# 启动容器
docker run -itd -p 3008:3008 --name bagentnode --privileged=true bmcagent:111
# 登录容器
docker exec -it bagentnode bash
|
这为我们将来的K8s部署创造了条件。
K8s编排服务
创建ReplicaSet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
## rs_node.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: rs-web-agent
labels:
app: rs-web-agent
spec:
replicas: 2
selector:
matchLabels:
app: rs-web-agent
template:
metadata:
name: rs-web-agent
labels:
app: rs-web-agent
spec:
containers:
- name: rs-web-agent
image: 10.10.200.11:5000/bmcwebagent:111
ports:
- containerPort: 3008
|
创建Service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
## svc_node.yml
## 端口映射到K8s集群中所有主机上
#apiVersion: v1
#kind: Service
#metadata:
# name: svc-web-agent
#spec:
# type: NodePort
# ports:
# - port: 3008
# nodePort: 30009
# selector:
# app: rs-web-agent
#
# 普通的服务
apiVersion: v1
kind: Service
metadata:
name: svc-web-agent
spec:
ports:
- port: 3008
selector:
app: rs-web-agent
|
在K8s集群中分别执行上面的两个文件:
1
2
|
kubectl apply -f rs_node.yml
kubectl apply -f svc_node.yml
|
分别执行命令,查看创建相关组件的情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@k8s51 agent]# kubectl get rs
NAME DESIRED CURRENT READY AGE
rs-web-agent 2 2 2 130m
[root@k8s51 agent]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.21.0.1 <none> 443/TCP 12d
svc-web-agent ClusterIP 10.21.195.32 <none> 3008/TCP 111m
[root@k8s51 agent]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
rs-web-agent-cm9h4 1/1 Running 0 132m 10.244.1.3 k8s53
rs-web-agent-dghzf 1/1 Running 0 132m 10.244.2.4 k8s54
|
最终我们观察到此NodeJS引用被成功的在 K8s 集群中两个不同的 worker 中启动了。
编排进阶
Deployment
通过Deployment对象,你可以轻松的做到以下事情:
- 创建ReplicaSet和Pod
- 滚动升级(不停止旧服务的状态下升级)和回滚应用(将应用回滚到之前的版本)
- 平滑地扩容和缩容
- 暂停和继续Deployment
另外,我们可以创建自己的namespace,为将来的应用做分组隔离。
1
2
3
4
5
|
# namespace.yml
apiVersion: v1
kind: Namespace
metadata:
name: bmc
|
下面我们用Deployment替代ReplicaSet来做Pod:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# deploy-node.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: rs-web-agent
namespace: bmc
labels:
app: rs-web-agent
spec:
replicas: 2
selector:
matchLabels:
app: rs-web-agent
template:
metadata:
name: rs-web-agent
labels:
app: rs-web-agent
spec:
containers:
- name: rs-web-agent
image: 10.10.200.11:5000/bmcwebagent:111
ports:
- containerPort: 3008
|
K8s对外提供服务
k8s向外界提供服务的几种方法port-forward
、NodePort
,ingress
。
port-forward 映射服务到端口
1
2
3
4
5
6
7
|
# 类似下面的命令
kubectl port-forward -n bmc service/svc-web-agent 30091:3008
# 执行上面这句之后,看本地的端口情况
[root@k8s54 home]# netstat -ano|grep 30091
tcp 0 0 127.0.0.1:30091 0.0.0.0:* LISTEN off (0.00/0/0)
tcp6 0 0 ::1:30091 :::* LISTEN off (0.00/0/0)
|
这种方式只能在本机IP地址上开启相应的端口。
NodePort 映射服务到节点端口
相对于上一种port-forward
来说,这一种要正式的多,NodePort
可以将其 转发到所有 k8s 节点的指定端口上,并且不会像port-forward
一样在前台运行。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# svc_node.yml
# 端口映射到K8s集群中所有主机上
apiVersion: v1
kind: Service
metadata:
name: svc-web-agent
spec:
type: NodePort
ports:
- port: 3008
nodePort: 30091
selector:
app: rs-web-agent
|
如果用上面NodePort的方式创建应用,大家可以观察到K8s集群中的每台主机的IP上都监听了30091端口。
通过 Ingress 暴露服务
ingress 是啥?其实,ingress 就是一个nginx
服务器。从本质上说,我们可以直接通过配置nginx
服务器来实现刚才说的访问方式,但是这样每次svc
发生变更了我们就要重新手动配置一遍,好麻烦的,于是就有聪明的人想出来了,为什么我们不把复杂的配置操作抽象成一个文件,这样有新的变更的话我们直接修改文件,不就可以避免直接操作nginx
服务器了么?于是,ingress
诞生了。ingress
本质上就是一个nginx
和许多个配置文件。
这种模式相对复杂,暂时不做介绍,大家可以自己探索。
应用日志
参考:https://www.cnblogs.com/operationhome/p/10907591.html
我们可以为所有的Docker应用指定日志文件路径,之后将worker主机的固定目录挂载到所有的Docker容器中。这样所有Docker的日志文件实际上都写入到了服务器的指定目录中,参考下面的Deployment编排文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
apiVersion: apps/v1
kind: Deployment
metadata:
name: rs-web-agent
namespace: bmc
labels:
app: rs-web-agent
spec:
replicas: 2
selector:
matchLabels:
app: rs-web-agent
template:
metadata:
name: rs-web-agent
labels:
app: rs-web-agent
spec:
containers:
- name: rs-web-agent
image: 10.10.200.11:5000/bmcwebagent:111
ports:
- containerPort: 3008
volumeMounts:
- name: rs-web-agent-log-volume
mountPath: /home/logs
volumes:
- name: rs-web-agent-log-volume
hostPath:
path: /bmclogs
|
参考汇总
https://zhuanlan.zhihu.com/p/337481698
https://blog.csdn.net/weixin_33896726/article/details/91875508
https://www.cnblogs.com/gaoyanbing/p/14031522.html
(完)