这里我们以简单的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-forwardNodePortingress

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

(完)