业务系统与中间件k8s容器化部署实践——redis+nodejs/springboot单体应用
单体应用### 业务镜像一般来自cicd推送的docker私库,这里手动创建一个demo,java/nodejs应用均可(在普通node节点操作)1.需要node环境,node -v ,没有就安装一下yum install node -y2.nodejs业务程序,文件内容如下:var http=require('http');var handleRequest = function(request
1.redis k8s部署
1.1创建创建一个namespace,缺省为default,创建套路kubectl apply -f XX.yaml
apiVersion: v1
kind: Namespace
metadata:
name: redis-namespace
1.2创建一个configmap,建议去掉redis.conf原配置文件里的注释,减少etcd存储消耗
kubectl create configmap redis-configmap --from-file=/etc/redis.conf -n redis-namespace
1.3宿主机/etc/redis.conf配置文件
dir /data
requirepass 12345
pidfile /data/redis.pid
port 6379
tcp-backlog 30000
timeout 0
tcp-keepalive 10
loglevel notice
logfile /data/redis.log
databases 16
#save 900 1
#save 300 10
#save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
maxclients 30000
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events KEA
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 1000
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
1.4创建一个deployment ,创建套路kubectl apply -f XXX.yaml ,这里数据卷一个挂载上面定义的configmap,一个宿主机hostPath
apiVersion: extensions/v1beta1 #注意v1版本不支持Deployment
kind: Deployment
metadata:
name: redis-deployment
namespace: redis-namespace #使用自定义namespace
spec:
replicas: 1
template:
metadata:
labels:
name: redis-label
spec:
containers:
- name: redis-container
image: redis
volumeMounts:
- name: myconfigmap #与volumes的name对应
mountPath: "/usr/local/etc" #与vomums的key为redis.conf的path拼接得到容器内redis配置文件绝对路径
- name: redis-data #容器内挂载点名称
mountPath: /data #容器内data保持路径,该路径在redis.conf配置了
command:
- "redis-server" #启动命令
args:
- "/usr/local/etc/redis/redis.conf" #带配置文件启动
volumes:
- name: myconfigmap
configMap:
name: redis-configmap #指定使用的configmap
items:
- key: redis.conf #该值为configmap创建--from-file的文件名
path: redis/redis.conf
- name: redis-data #数据卷名称,需要与容器内挂载点名称一致
hostPath:
path: /var/lib/redis #将容器挂载点名称相同的path挂载到宿主机path(但这种方式有局限性,pod分配到其它node数据就丢失了,需要挂载到NFS文件系统?)
1.5测试
#查看
kubectl get pods -n redis-namespace -o wide
#进入容器访问
kubectl exec -it redis-deployment-556c5d85bb-vxv6b /bin/bash -n redis-namespace
#redis操作测试
连接redis-cli 认证auth 12345 查看数据目录:/var/lib/redis
#暴露redis-deployment这个服务,方便后面被其它k8s容器,并暴露一个外网端口(正式环境一般中间件不暴露外网端口)
kubectl expose deployment redis-deployment -n redis-namespace --port=6379 --type=LoadBalancer
#检查该服务
kubectl get service -n redis-namespace
内容为redis-deployment LoadBalancer 10.1.59.127 <pending> 6379:30753/TCP
测试连接:telnet 127.0.0.1 30753 telnet 10.1.59.127 6379
2.业务应用 k8s部署
为方便这里以nodejs为例,Java应用类似.
2.1.需要node环境,node -v ,没有就安装一下yum install node -y
2.2 nodejs业务程序,文件内容如下
var http=require('http');
var handleRequest = function(request, response) {
console.log('Received request for URL: ' + request.url);
response.writeHead(200);
response.end('Hello World!');
};
var www = http.createServer(handleRequest);
www.listen(8080);
2.3 直接启动一下:node server.js,测试:curl 127.0.0.1:8080
2.4 在service.js同级目录,创建Dockerfile,如果使用java可使用基础镜像FROM java:8,文件内容如下
FROM node:6.9.2
EXPOSE 8080
COPY server.js .
CMD node server.js
2.5 镜像构建并推送到docker registry私库
1.安装registry仓库
docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --name myregistry registry:2
2.构建nodejs应用镜像192.168.203.134:5000/hello-world:v1
docker build -t 192.168.203.134:5000/hello-world:v1 .
docker push 192.168.203.134:5000/hello-world:v1 .
3.docker push默认走https协议,如果要http协议push,需要配置/etc/docker/daemon.json,内容为:{
"registry-mirrors": ["https://5c3uuctj.mirror.aliyuncs.com","https://hub- mirror.c.163.com", "https://reg-mirror.qiniu.com"],
"insecure-registries":["192.168.203.134:5000"]
}
4.重启:systemctl restart docker && docker restart myregistry ,再推送
docker push 192.168.203.134:5000/hello-world:v1 .
5.检查一下
curl http://192.168.203.134:5000/v2/_catalog
2.6 k8s 部署hello-world
1.启动容器
kubectl run hello-world --image=192.168.203.134:5000/hello-world:v2 --port=8080
2.暴露该服务一个外网可访问的随机IP
kubectl expose deployment hello-world --type=LoadBalancer
3.查看与测试
kubectl get services
curl 192.168.203.134:随机IP 或 ClusterIp:8080
3.k8s业务容器访问k8s redis容器
3.1代码修改,引入redis模块,service.js目录npm install redis安装redis依赖,使用nodejs读写redis,连接参数REDIS_PORT,REDIS_HOST从环境变量读取:process.env.REDIS_PORT,process.env.REDIS_HOST
var http=require('http');
var redis=require('redis');
var handleRequest = function(request, response) {
console.log('Received request for URL: ' + request.url);
RDS_PORT = process.env.REDIS_PORT,
RDS_HOST = process.env.REDIS_HOST,
RDS_OPTS = {auth_pass:12345} ,
client = redis.createClient(RDS_PORT, RDS_HOST, RDS_OPTS);
client.on('ready', function(res){
console.log('redis连接事件')
})
client.set("now",new Date(),redis.print);
client.get("now", function(err, reply){
console.log(reply);
response.writeHead(200);
response.end('当前时间:'+reply);
})
};
var www = http.createServer(handleRequest);
www.listen(8080);
3.2 修改Dockerfile,CMD命令增加npm intall redis,否则后面启动k8s应用容器报错缺少redis模块(kubectl logs POD名称)
FROM node:6.9.2
EXPOSE 8080
COPY server.js .
CMD npm install redis && node server.js
3.3重新构建推送私库并k8s部署
1.重新构建并推送
docker build -t 192.168.203.134:5000/hello-world:v2 .
docker push 192.168.203.134:5000/hello-world:v2
2.更新k8s hello-world服务的镜像,重新kubectl apply -f XXX.yaml,
或kubectl set image deployment/hello-world hello-world=192.168.203.134:5000/hello-world:v2
3.查看日志
kubectl get service,pod 获取pod名称
kubectl logs --tail 222 -f pod/hello-world-699d4b48cb-r4tpb 进行动态查看日志
日志内容是这样的,因为service.js的redis连接参数需要读取环境变量process.env.REDIS_PORT,process.env.REDIS_HOST,而
通过kubectl run xx kubectl expose xx这样直接部署一个deployment不便指定环境变量及其它,需要使用yaml配置文件方式启动
3.4 通过yaml配置文件启动redis-deployment, kubectl apply -f xxxx.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: hello-world
namespace: default #不一定要与其它服务如redis-deployment在同一命名空间
spec:
replicas: 1
selector:
matchLabels:
app: myweb
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: myweb
spec:
containers:
- name: hello-world
image: 192.168.203.134:5000/hello-world:v2
volumeMounts:
- name: time-zone
mountPath: /etc/localtime
ports:
- containerPort: 8080
env:
- name: REDIS_HOST
value: 192.168.203.134 #10.1.59.127 #redis-deployment这个service暴露外网nodePort,可以通过外网IP:NodePort或CLUSTER_IP:8080访问
- name: REDIS_PORT
value: "30753" #"6379"
volumes:
- name: time-zone
hostPath:
path: /etc/localtime
3.5 测试
1.删除原deployment,service可以不删
kubectl delete deployment hello-world
2.启动k8s容器服务
kubectl apply -f XXX.yaml
3.查看日志
kubectl get pods
kubectl logs --tail 222 -f pod/hello-world-68995967dd-hq9c6
请求测试与hello-world的pod日志输出
3.6 REDIS_PORT,REDIS_HOST改为configmap读取,重新kubectl apply .
1.创建configmap
kubectl create configmap redis-config --from-literal=redis.port=6379 --from-literal=redis.host=10.1.59.127
2.hello-world的deployment yaml资源描述env部分修改如下:
env:
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: redis-config
key: redis.host
- name: REDIS_PORT
valueFrom:
configMapKeyRef:
name: redis-config
key: redis.port
3.7 springboot单体应用部署
1.修改Dockerfile的基础镜像,CMD启动命令的区别等
2.查看application-dev.yml REDIS主要连接参数如下:
spring:
redis:
host: XXXX
port: 6379
key为spring.redis.host spring.redis.port
3.创建configmap:kubectl create configmap redis-config --from-literal=redis.port=6379 --
from-literal=redis.host=10.1.59.127
4.deployment资源描述文件env部分指定spring.redis.host spring.redis.port这两个变量的值
env:
- name: spring.redis.host
valueFrom:
configMapKeyRef:
name: redis-config
key: redis.host
- name: spring.redis.port
valueFrom:
configMapKeyRef:
name: redis-config
key: redis.port
3.8 关于数据持久化
k8s pod分配是动态的,redis数据目录挂载到宿主机很可能造成数据丢失,需要向configmap一样的NFS进行集中存储(参考https://www.cnblogs.com/DaweiJ/articles/9131762.html),或REDIS等系统不进行k8s容器化部署
更多推荐
所有评论(0)