一、Dubbo微服务概述
1.1: dubbo介绍
1.2: 部署内容
二、实验环境架构
2.1: 架构
1.1 架构图解
1.最上面一排为K8S集群外服务
1.1 代码仓库使用基于git的gitee
1.2 注册中心使用3台zk组成集群
1.3 用户通过ingress暴露出去的服务进行访问
2.中间层是K8S集群内服务
2.1 jenkins以容器方式运行,数据目录通过共享磁盘做持久化
2.2 整套dubbo微服务都以POD方式交付,通过zk集群通信
2.3 需要提供的外部访问的服务通过ingress方式暴露
3.最下层是运维主机层
3.1 harbor是docker私有仓库,存放docker镜像
3.2 POD相关yaml文件创建在运维主机特定目录
3.3 在K8S集群内通过nginx提供的下载连接应用yaml配置
1.2 交付说明:
docker虽然可以部署有状态服务,但如果不是有特别需要,还是建议不要部署有状态服务
K8S同理,也不建议部署有状态服务,如mysql,zk等。
因此手动将zookeeper创建集群提供给dubbo使用
2.2: 有状态服务和无状态服务
有状态---数据需要持久化,不能随意扩容
有状态软件也可以拆分成无状态(功能)和有状态部分(数据持久化)
三、部署zookeeper集群
3.1: zookeeper概述
3.2: 部署zookeeper
集群分布:7-11,7-12,7-21
zk是java服务,需要依赖jdk
3.2.1: Jdk下载
Zookeeper依赖于java环境
7-11,7-12,7-21
#上传解压
[root@hdss7-11 src]# mkdir /usr/java/ && tar xf /opt/src/jdk-8u221-linux-x64.tar.gz -C /usr/java/
#软链接
[root@hdss7-11 src]# ln -s /usr/java/jdk1.8.0_221/ /usr/java/jdk
3.2.2: java环境变量
cat >>/etc/profile <<'EOF'
#JAVA HOME
export JAVA_HOME=/usr/java/jdk
export PATH=$JAVA_HOME/bin:$JAVA_HOME/bin:$PATH
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
EOF
# 使环境变量生效
source /etc/profile
[root@hdss7-11 ~]# java -version
3.2.3: 二进制安装zookeeper
#下载地址
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
tar -zxf zookeeper-3.4.14.tar.gz -C /opt/
ln -s /opt/zookeeper-3.4.14/ /opt/zookeeper
创建zk配置文件:
cat >/opt/zookeeper/conf/zoo.cfg <<'EOF'
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
dataLogDir=/data/zookeeper/logs
clientPort=2181
server.1=zk1.od.com:2888:3888
server.2=zk2.od.com:2888:3888
server.3=zk3.od.com:2888:3888
EOF
创建相关目录
mkdir -p /data/zookeeper/data
mkdir -p /data/zookeeper/logs
创建集群配置—myid
给每个zk不同的myid,以便区分主从
#7-11上
echo 1 > /data/zookeeper/data/myid
#7-12上
echo 2 > /data/zookeeper/data/myid
#7-21上
echo 3 > /data/zookeeper/data/myid
修改dns解析
到7.11上增加dns解析记录
vi /var/named/od.com.zone
...
zk1 A 10.4.7.11
zk2 A 10.4.7.12
zk3 A 10.4.7.21
systemctl restart named
#验证结果
~]# dig -t A zk1.od.com +short
10.4.7.11
将zk启动放进开机自启动
启动zk集群
在每台zk机器上都执行此操作
/opt/zookeeper/bin/zkServer.sh start
检查zk启动情况
~]# ss -ln|grep 2181
tc
检查zk集群情况
[root@hdss7-11 ~]# /opt/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Mode: follower
[root@hdss7-12 ~]# /opt/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Mode: leader
[root@hdss7-21 ~]# /opt/zookeeper/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Mode: follower
准备java运行底包
运维主机上操作
四、部署jenkins服务配置ci流水线
4.1: 部署jenkins
准备镜像的操作在7.200运维机上完成jenkins镜像
下载官方镜像
docker pull jenkins/jenkins:2.190.3
docker tag jenkins/jenkins:2.190.3 harbor.od.com/public/jenkins:v2.190.3
docker push harbor.od.com/public/jenkins:v2.190.3
#生成密钥
[root@hdss7-200 ~]# ssh-keygen -t rsa -b 2048 -C "731616191@qq.com" -N "" -f /root/.ssh/id_rsa
#生成ssh密钥,dubbo项目使用git拉代码,走的ssh或者http,把私钥封装到jenkins镜像里,git服务器上放着公钥
cp /root/.ssh/id_rsa /data/dockerfile/jenkins/
自定义Dockerfile
cat >/data/dockerfile/jenkins/Dockerfile <<'EOF'
FROM harbor.od.com/public/jenkins:v2.190.3
#定义启动jenkins的用户
USER root
#修改时区为东八区
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
echo 'Asia/Shanghai' >/etc/timezone
#加载用户密钥,使用ssh拉取dubbo代码需要
ADD id_rsa /root/.ssh/id_rsa
#加载运维主机的docker配置文件,里面包含登录harbor仓库的认证信息。
ADD config.json /root/.docker/config.json
#在jenkins容器内安装docker客户端,docker引擎用的是宿主机的docker引擎,安装后就可以使用docker命令了拉取上传harbor镜像
ADD get-docker.sh /get-docker.sh
# 跳过ssh时候输入yes的交互步骤,并执行安装docker
RUN echo " StrictHostKeyChecking no" >/etc/ssh/ssh_config &&\
/get-docker.sh –mirror Aliyun
EOF
–mirror Aliyun 可以不写
获取docker.sh脚本:
curl -fsSL get.docker.com -o /data/dockerfile/jenkins/get-docker.sh
chmod u+x /data/dockerfile/jenkins/get-docker.sh
拷贝config.json文件:
cp /root/.docker/config.json /data/dockerfile/jenkins/
harbor中创建私有仓库infra
制作镜像
cd /data/dockerfile/jenkins/
docker build . -t harbor.od.com/infra/jenkins:v2.190.3
docker push harbor.od.com/infra/jenkins:v2.190.3
容器测试登录gitee
公钥信息(pub)粘贴进去,测试登录
[root@hdss7-200 jenkins]# docker run --rm harbor.od.com/infra/jenkins:v2.190.3 ssh -i /root/.ssh/id_rsa -T git@gitee.com
4.2: 准备jenkins运行环境
4.2.1: 专有名称空间和secret资源
创建专有namespace—为jenkins
创建专有名词空间infra的目录是将jenkins等运维相关软件放到同一个namespace下,便于统一管理以及和其他资源分开
[root@hdss7-21 opt]# kubectl create ns infra
#该空间将jenkins存进去
创建访问harbor的secret规则
三种secret
三种secret
Tls ,docker-register,token使用的
Secret用来保存敏感信息,例如密码、OAuth 令牌和 ssh key等,有三种类型:
1.Opaque:
base64 编码格式的 Secret,用来存储密码、密钥等,可以反解,加密能力弱
2.kubernetes.io/dockerconfigjson:
用来存储私有docker registry的认证信息。
3..kubernetes.io/service-account-token:
用于被serviceaccount引用,serviceaccout 创建时Kubernetes会默认创建对应的secret
前面dashborad部分以及用过了
创建
访问docker的私有仓库,必须要创建专有的secret类型,创建方法如下:
kubectl create secret docker-registry harbor \
--docker-server=harbor.od.com \
--docker-username=admin \
--docker-password=123456 \
-n infra
# 查看结果
~]# kubectl -n infra get secrets
NAME TYPE DATA AGE
default-token-rkg7q kubernetes.io/service-account-token 3 19s
harbor kubernetes.io/dockerconfigjson 1 12s
dashboar的查看
解释命令:
创建一条secret,资源类型是docker-registry,名字是 harbor
并指定docker仓库地址、访问用户、密码、仓库名
4.2.1: 准备nfs共享存储
将jenkins数据存放在k8s集群之外的共享存储
jenkins中一些数据需要持久化的,可以使用共享存储进行挂载:
这里使用最简单的NFS共享存储,因为k8s默认支持nfs模块
如果使用其他类型的共享存储
运维机部署NFS
#在200主机上
yum install nfs-utils -y
echo
'/data/nfs-volume 10.4.7.0/24(rw,no_root_squash)' >>/etc/exports
mkdir -p /data/nfs-volume/jenkins_home
systemctl start nfs
systemctl enable nfs
# 查看结果
~]# showmount -e
Export list for hdss7-200:
/data/nfs-volume 10.4.7.0/24
node节点安装nfs
yum install nfs-utils -y
4.2.3: 运维机创建jenkins资源清单
mkdir /data/k8s-yaml/jenkins
创建depeloy清单
有两个需要注意的地方:
- 挂载了宿主机的docker.sock
使容器内的docker客户端可以直接与宿主机的docker引擎进行通信 - 在使用私有仓库的时候,资源清单中,一定要声明:
imagePullSecrets:
- name: harbor
cat >/data/k8s-yaml/jenkins/dp.yaml <<EOF
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: jenkins
namespace: infra
labels:
name: jenkins
spec:
replicas: 1
selector:
matchLabels:
name: jenkins
template:
metadata:
labels:
app: jenkins
name: jenkins
spec:
volumes:
data #卷名称,与容器的volume的名称一样
nfs: #nfs类型的卷
server: hdss7-200
path: /data/nfs-volume/jenkins_home
- name: docker #名字叫docker的卷
hostPath: #hostpath类型
path: /run/docker.sock #宿主机的文件,挂载到jenkins
type: ''
containers:
- name: jenkins
image: harbor.od.com/infra/jenkins:v2.190.3
imagePullPolicy: IfNotPresent #镜像拉取策略(awlays远程拉,never本地拉,ifnotpresent本地没有去远程仓库啦)
ports:
- containerPort: 8080
protocol: TCP
env: #环境变量
- name: JAVA_OPTS
value: -Xmx512m -Xms512m
volumeMounts:
mountPath: /var/jenkins_home #data卷挂载到该容器路径
- name: docker
mountPath: /run/docker.sock
imagePullSecrets:
- name: harbor #叫harbor的secret(该镜像是私有的)
securityContext:
runAsUser: 0 #root启动jenkins
strategy:
type: RollingUpdate #滚动升级
rollingUpdate: #滚动升级方法升级jenkins
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7 #留7份jenkins滚动版本
progressDeadlineSeconds: 600 #容器判定启动时间
EOF
解析:
声明拉取harbor镜像的secret
将容器的jenkins目录挂载到运维主机
将主机的/run/docker.sock挂载到容器中
选择jenkins升级方法为滚动升级
创建service清单
cat >/data/k8s-yaml/jenkins/svc.yaml <<EOF
kind: Service
apiVersion: v1
metadata:
name: jenkins
namespace: infra
spec:
ports:
- protocol: TCP
port: 80 #监听在clusterip上的端口,也就是service
targetPort: 8080 #容器端口
selector:
app: jenkins
EOF
创建ingress清单
cat >/data/k8s-yaml/jenkins/ingress.yaml <<EOF
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: jenkins
namespace: infra
spec:
rules:
- host: jenkins.od.com
http:
paths:
- path: /
backend:
serviceName: jenkins
servicePort: 80
EOF
应用jenkins资源配置清单
kubectl create -f http://k8s-yaml.od.com/jenkins/dp.yaml
kubectl create -f http://k8s-yaml.od.com/jenkins/svc.yaml
kubectl create -f http://k8s-yaml.od.com/jenkins/ingress.yaml
#启动时间很长,等待结果
kubectl get pod -n infra
查看日志,最终显示完整启动,
配置dns解析
vi /var/named/od.com.zone
jenkins A 10.4.7.10
# 重启服务
systemctl restart named
[root@hdss7-11 src]# dig -t A jenkins.od.com @10.4.7.11 +short
10.4.7.10
验证jenkins容器状态—重要
docker exec -it 8ff92f08e3aa /bin/bash
# 查看用户
whoami
# 查看时区
date
# 查看是否能用宿主机的docker引擎
docker ps
# 看是否能免密访问gitee
ssh -i /root/.ssh/id_rsa -T git@gitee.com
# 是否能访问是否harbor仓库
docker login harbor.od.com
#因为在jenkins容器中安装了docker客户端,挂载了与宿主机通信额socket文件,所以可以在容器执行容器命令
登录jenkins
查看登录密码
[root@hdss7-200 jenkins]# cat /data/nfs-volume/jenkins_home/secrets/initialAdminPassword
1e13eed72e2e426ab160746c3685b29a
#跳过插件
#配置管理员用户
admin
admin123
替换jenkins插件源
cd /data/nfs-volume/jenkins_home/updates
sed -i 's#http:\/\/updates.jenkins-ci.org\/download#https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins#g' default.json
sed -i 's#http:\/\/www.google.com#https:\/\/www.baidu.com#g' default.json
Jenkins初始化
浏览器访问http://jenkins.od.com,使用前面的密码进入jenkins
进入后操作:
跳过安装自动安装插件的步骤
在manage jenkins->Configure Global Security菜单中设置
2.1 允许匿名读:勾选allow anonymous read access
2.2 允许跨域:勾掉prevent cross site request forgery exploits
搜索并安装蓝海插件blue ocean
设置用户名密码为admin:admin123
安全访问优化
安装pipine
小结
4.3: 安装部署maven
4.3.1: 二进制安装
200主机
#下载地址
https://archive.apache.org/dist/maven/maven-3/3.6.2/binaries/apache-maven-3.6.2-bin.tar.gz
#下载解压
wget https://archive.apache.org/dist/maven/maven-3/3.6.1/binaries/apache-maven-3.6.1-bin.tar.gz
mkdir /data/nfs-volume/jenkins_home/maven-3.6.1-8u232
tar -zxf apache-maven-3.6.1-bin.tar.gz -C /data/nfs-volume/jenkins_home/maven-3.6.1-8u232
cd /data/nfs-volume/jenkins_home/maven-3.6.1-8u232/apache-maven-3.6.1
mv ./* ..
查看jenkins-jdk版本
#修改maven打包镜像地址
Settings文件是全局生效的,pom.xml文件是写在编译的目录里.pom文件优先级更高
[root@hdss7-200 conf]# vi /data/nfs-volume/jenkins_home/maven-3.6.1-8u232/conf/settings.xml
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
更换maven的编译环境的jdk版本
3.6版本maven默认是使用环境变量jdk版本
200中进入Jenkins挂载目录中下载jdk1.7
Maven编译jdk版本相关的3个文件
/data/nfs-volume/jenkins_home/maven-3.6.1-8u232/conf/settings.xml
/data/nfs-volume/jenkins_home/workspace/dubbo-demo/dubbo-demo-service/3/pom.xml
/data/nfs-volume/jenkins_home/maven-3.6.1-8u232/bin/mvn
五、交付dubbo服务提供者到k8s
5.1: 制作dubbo微服务的镜像
5.1.1: 准备jre底包(7版本有一个7u80)
[root@hdss7-200 jre8]# docker pull docker.io/stanleyws/jre8:8u112 #老王docker官方的镜像
[root@hdss7-200 jre8]# docker images |grep jre
stanleyws/jre8 8u112 fa3a085d6ef1 2 years ago 363MB
[root@hdss7-200 jre8]# docker tag fa3a085d6ef1 harbor.od.com/public/jre:8u112
[root@hdss7-200 jre8]# docker push harbor.od.com/public/jre:8u112
5.1.2: 自定义dockerfile
root@hdss7-200 dockerfile]# mkdir jre8
[root@hdss7-200 dockerfile]# cd jre8/
[root@hdss7-200 jre8]# pwd
/data/dockerfile/jre8
自定义dockerfile,基于java环境的类似centos镜像(harbor.od.com/public/jre:8u112)
[root@hdss7-200 jre8]# vi Dockfile
FROM harbor.od.com/public/jre:8u112
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
echo'Asia/Shanghai' >/etc/timezone
ADD config.yml /opt/prom/config.yml
ADD jmx_javaagent-0.3.1.jar /opt/prom/
WORKDIR /opt/project_dir
ADD entrypoint.sh /entrypoint.sh
CMD"/entrypoint.sh"]
#workdir—>要求工作目录为/opt/project_dir
Dockerfile中的WORKDIR指令用于指定容器的一个目录,容器启动时执行的命令会在该目录下执行,相当于设置了容器的工作目录。
5.1.3: 准备dockerfile提交的文件
1.准备java-agent的jar包(监控软件需要用到)
[root@hdss7-200 jre8]# wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.3.1/jmx_prometheus_javaagent-0.3.1.jar -O jmx_javaagent-0.3.1.jar
#通过这个jar包,取jvm信息(监控信息)
2.准备config.yml和
[root@hdss7-200 jre8]# vi config.yml
---
rules:
- pattern: '.*'
3.准备entrypoint.sh
[root@hdss7-200 jre8]# vi entrypoint.sh
#!/bin/sh
M_OPTS="-Duser.timezone=Asia/Shanghai -javaagent:/opt/prom/jmx_javaagent-0.3.1.jar=$(hostname -i):${M_PORT:-"12346"}:/opt/prom/config.yml"
#$(hostname -i)pod的ip
#):${M_PORT:-"12346"}:/端口12346,M_PORT变量默认值为- 12346,如果给了值,就用新值
#/opt/prom/config.yml 指定监控规则配置文件
C_OPTS=${C_OPTS}
#阿波罗监控用
JAR_BALL=${JAR_BALL}
#将当前容器环境变量中叫JAR_BALL环境变量存到变量中去(由资源配置清单提供变量)
exec java -jar ${M_OPTS} ${C_OPTS} ${JAR_BALL}
#jar的包,exec把当前entrypoint进程权给java了.
[root@hdss7-200 jre8]# chmod +x entrypoint.sh #加权限
5.1.4: 建立base仓库,准备上传构建的新基础镜像
构建dubbo微服务的底包并推到harbor仓库
[root@hdss7-200 jre8]# docker build . -t harbor.od.com/base/jre8:8u112
[root@hdss7-200 jre8]# docker push harbor.od.com/base/jre8:8u112
5.2: dubbo-service-使用Jenkins进行持续构建交付服务的提供者
5.2.1: Jenkins创建流水线
5.2.2: Jenkins构建项目的10个参数
jenkins流水线配置的java项目的十个常用参数:
参数名 | 作用 | 举例或说明 |
app_name | 项目名 | dubbo_demo_service |
image_name | docker镜像名 | app/dubbo-demo-service |
git_repo | 项目的git地址 | https://x.com/x/x.git |
git_ver | 项目的git分支或版本号 | master |
add_tag | 镜像标签8位+常用时间戳 | 191203_1830 |
mvn_dir | 执行mvn编译的目录 | ./ |
target_dir | 编译产生包的目录 | ./target |
mvn_cmd | 编译maven项目的命令 | mvc clean package -Dmaven. |
base_image | 项目的docker底包 | 不同的项目底包不一样,下拉选择 |
maven | maven软件版本 | 不同的项目可能maven环境不一样 |
mvn clean package -Dmaven.test.skip=true
base/jre7:7u80
base/jre8:8u112
3.6.1-8u232
3.2.5-8u045
2.2.1-6u025
5.2.3: Pipeline Script
上面定义的参数,在script中使用了
pipeline {
agent any
stages {
stage('pull') { //get project code from repo
steps {
sh "git clone ${params.git_repo} ${params.app_name}/${env.BUILD_NUMBER} && cd ${params.app_name}/${env.BUILD_NUMBER} && git checkout ${params.git_ver}"
}
}
stage('build') { //exec mvn cmd
steps {
sh "cd ${params.app_name}/${env.BUILD_NUMBER} && /var/jenkins_home/maven-${params.maven}/bin/${params.mvn_cmd}"
}
}
stage('package') { //move jar file into project_dir
steps {
sh "cd ${params.app_name}/${env.BUILD_NUMBER} && cd ${params.target_dir} && mkdir project_dir && mv *.jar ./project_dir"
}
}
stage('image') { //build image and
push to registry
steps {
writeFile file: "${params.app_name}/${env.BUILD_NUMBER}/Dockerfile", text: """FROM harbor.od.com/${params.base_image}
ADD ${params.target_dir}/project_dir /opt/project_dir"""
sh "cd ${params.app_name}/${env.BUILD_NUMBER} && docker build -t harbor.od.com/${params.image_name}:${params.git_ver}_${params.add_tag} . && docker push harbor.od.com/${params.image_name}:${params.git_ver}_${params.add_tag}"
}
}
}
}
解析
Jenkins的初始目录是在/data/nfs-volume/jenkins_home/workspace/
#注意:
参数base_image,是容器运行的基础环境,可以有2个版本,1.7jdk,1.8jdk
docker pull harbor.od.com:180/base/jre8:8u112 ---对应这个地址
#参数:maven,针对了不同mvn打包版本--à对应不同编译jdk(需要下载)
Pom文件
#在代码目录中
5.2.4: 声明参数-构建
mvn clean package -Dmaven.test.skip=true
clean清除本地缓存
package 不保留在本地,install 保留在本地
-e 只输出错误
-q 静默输出
添加app仓库(私有)
开始构建
小结:---------------------
整个jenkins构建流程
首先: 制作dubbo微服务基础镜像base
1.使用k8s集群里的jenkins容器,创建了一个流水线
2.流水线:拉取了gitee上的dubbo-demo-service的java源码包,并使用maven编译,该maven已经在200主机挂载的jenkins目录的maven目录中修改了settings文件的打包阿里地址
3.打包完源码包后,使用jenkins容器的docker给包打个标签,推送到harbor仓库
4.下一步是创建资源配置清单,使用这个镜像包,安装到k8s集群
5.3: dubbo-service创建资源配置清单制作pod
准备资源清单
创建清单操作都在7.200上操作
创建depeloy清单
[root@hdss7-200 dubbo-server]# mkdir /data/k8s-yaml/dubbo-server
cat>/data/k8s-yaml/dubbo-server/dp.yaml <<EOF
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-service
namespace: app
labels:
name: dubbo-demo-service
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-demo-service
template:
metadata:
labels:
app: dubbo-demo-service
name: dubbo-demo-service
spec:
containers:
- name: dubbo-demo-service
image: harbor.od.com/app/dubbo-demo-service:master_191201_1200
ports:
- containerPort: 20880
protocol: TCP
env:
- name: JAR_BALL #传递给容器启动时的脚本变量-à环境变量
value: dubbo-server.jar
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
#secret名称
restartPolicy: Always
terminationGracePeriodSeconds: 30 #启动超时时间
securityContext:
runAsUser: 0 #0代表root方式启动
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600
EOF
应用资源配置清单
创建K8S资源的操作,在任意node节点上操作即可
创建app名称空间
kubectl create namespace app
创建secret资源
我们的业务镜像是harbor中的私有项目,所以需要创建docker-registry的secret资源:
kubectl -n app \
create secret docker-registry harbor\
--docker-server=harbor.od.com \
--docker-username=admin \
--docker-password=123456
应用资源清单
kubectl apply -f http://k8s-yaml.od.com/dubbo-server/dp.yaml
3分钟后检查启动情况
# 检查pod是否创建:
~]# kubectl -n app get pod
NAME READY STATUS RESTARTS AGE
dubbo-demo-service-79574b6879-cxkls 1/1 Running 0 24s
# 检查是否启动成功:
~]# kubectl -n app logs dubbo-demo-service-79574b6879-cxkls --tail=2
Dubbo server started
Dubbo 服务端已经启动
到zk服务器检查是否有服务注册
sh /opt/zookeeper/bin/zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /
[dubbo, zookeeper]
[zk: localhost:2181(CONNECTED) 1] ls /dubbo
[com.od.dubbotest.api.HelloService]
#zookeeper没有做开机自启动
到此---dubbo-server服务交付成功(provider)
六、交付dubbo-monitor服务到k8s集群
dobbo-monitor源码地址: https://github.com/Jeromefromcn/dubbo-monitor.git
dubbo-monitor是监控zookeeper状态的一个服务,另外还有dubbo-admin,效果一样
6.1: 制作dobbo-monitor镜像
制作镜像在管理机7.200上操作
下载源码
cd /opt/src
wget https://github.com/Jeromefromcn/dubbo-monitor/archive/master.zip
yum -y install unzip
unzip dubbo-monitor-master.zip
mv dubbo-monitor-mster /data/dockerfile/dubbo-monitor
cd /data/dockerfile/dubbo-monitor
修改配置文件:
直接覆盖它原始的配置
其实它原本就没什么内容,只是修改了addr,端口,目录等
cat >dubbo-monitor-simple/conf/dubbo_origin.properties <<'EOF'
dubbo.container=log4j,spring,registry,jetty
dubbo.application.name=dubbo-monitor
dubbo.application.owner=OldboyEdu
dubbo.registry.address=zookeeper://zk1.od.com:2181?backup=zk2.od.com:2181,zk3.od.com:2181
dubbo.protocol.port=20880
dubbo.jetty.port=8080
dubbo.jetty.directory=/dubbo-monitor-simple/monitor
dubbo.statistics.directory=/dubbo-monitor-simple/statistics
dubbo.charts.directory=/dubbo-monitor-simple/charts
dubbo.log4j.file=logs/dubbo-monitor.log
dubbo.log4j.level=WARN
EOF
优化monitor启动脚本
# 修改jvm资源限制(非必须)
sed -i '/Xmx2g/ s#128m#16m#g' ./dubbo-monitor-simple/bin/start.sh
sed -i '/Xmx2g/ s#256m#32m#g' ./dubbo-monitor-simple/bin/start.sh
sed -i '/Xmx2g/ s#2g#128m#g' ./dubbo-monitor-simple/bin/start.sh
sed -i '/Xmx1g/ s#2g#128m#g' ./dubbo-monitor-simple/bin/start.sh
# 修改nohup为exec不能改,去掉改行最后的&符号
sed -ri 's#^nohup(.*) &#exec\1#g' ./dubbo-monitor-simple/bin/start.sh
# 删除exec命令行后面所有行
sed -i '66,$d' ./dubbo-monitor-simple/bin/start.sh
#复制到/data/dockerfile文件夹
[root@hdss7-200 ~]# cp -a dubbo-monitor /data/dockerfile/
[root@hdss7-200 dubbo-consumer]# cat /data/dockerfile/dubbo-monitor/Dockerfile
FROM jeromefromcn/docker-alpine-java-bash
#使用的是官方docker镜像
MAINTAINER Jerome Jiang
COPY dubbo-monitor-simple/ /dubbo-monitor-simple/
CMD /dubbo-monitor-simple/bin/start.sh
构建并上传
docker build . -t harbor.od.com/infra/dubbo-monitor:latest
docker push harbor.od.com/infra/dubbo-monitor:latest
6.2: 创建资源配置清单
准备目录
mkdir /data/k8s-yaml/dubbo-monitor
cd /data/k8s-yaml/dubbo-monitor
创建deploy资源文件
cat >dp.yaml <<EOF
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-monitor
namespace: infra
labels:
name: dubbo-monitor
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-monitor
template:
metadata:
labels:
app: dubbo-monitor
name: dubbo-monitor
spec:
containers:
- name: dubbo-monitor
image: harbor.od.com/infra/dubbo-monitor:latest
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 20880
protocol: TCP
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600
EOF
创建service资源文件
cat >svc.yaml <<EOF
kind: Service
apiVersion: v1
metadata:
name: dubbo-monitor
namespace: infra
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: dubbo-monitor
EOF
创建ingress资源文件
cat >ingress.yaml <<EOF
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: dubbo-monitor
namespace: infra
spec:
rules:
- host: dubbo-monitor.od.com
http:
paths:
- path: /
backend:
serviceName: dubbo-monitor
servicePort: 8080
EOF
6.3: 创建dubbo-miniotr服务
应用资源配置清单
在任意node节点
kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/dp.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/svc.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-monitor/ingress.yaml
验证:
~]# kubectl -n infra get pod
NAME READY STATUS RESTARTS AGE
dubbo-monitor-d9675688c-sctsx 1/1 Running 0 29s
jenkins-7cd8b95d79-6vrbn 1/1 Running 0 3d2h
添加dns解析
这个服务是有web页面的,创建了ingress和service资源的,所以需要添加dns解析
vi /var/named/od.com.zone
dubbo-monitor A 10.4.7.10
重启并验证
systemctl restart named
dig -t A dubbo-monitor.od.com @10.4.7.11 +short
访问monitor的web页面
访问dubbo-monitor.od.com
这里已经可以看到我们之前部署的dubbo-demo-service服务了,启动了两个进程来提供服务。
至此,dubbo-monitor监控服务已经部署完成。
七、交付dubbo服务消费者到k8s集群
7.1: 构建docker镜像
7.1.1: 获取私有仓库代码
之前创建的dubbo-service是微服务的提供者,现在创建一个微服务的消费者
使用git@gitee.com:noah-luo/dubbo-demo-web.git这个私有仓库中的代码构建消费者
先从https://gitee.com/sunx66/dubbo-demo-service这里fork到自己仓库,在设为私有
并修改zk的配置
7.1.2: 配置流水线
之前已经在jenkins配置好了流水线,只需要填写参数就行了。
参数名 | 参数值 |
app_name | dubbo-demo-consumer |
image_name | app/dubbo-demo-consumer |
git_repo | https://gitee.com/jinmuyan222/dubbo-demo-web.git |
git_ver | master |
add_tag | 191201_1800 |
mvn_dir | ./ |
target_dir | ./dubbo-client/target |
mvn_cmd | mvn clean package -e -q -Dmaven.test.skip=true |
base_image,harbor-base镜像地址 | base/jre8:8u112 |
maven | 3.6.1 |
#Target_dir目录为编译完成项目后,产生的jar/war包所在的目录,需要问写代码的人
或者看下git包的目录
https://gitee.com/jinmuyan222/dubbo-demo-web.git
可以将/root/.m2./repository挂载出来,防止pod重启丢失了
7.1.3: 查看构建结果
如果构建不报错,则应该已经推送到harbor仓库中了,这时我们直接再给镜像一个新tag,以便后续模拟更新
docker tag \
harbor.od.com/app/dubbo-demo-consumer:master_200506_1430 \
harbor.od.com/app/dubbo-demo-consumer:master_200510_1430
docker push harbor.od.com/app/dubbo-demo-consumer:master_200510_1430
查看harbor仓库
7.2: 准备资源配置清单
先准备目录
mkdir /data/k8s-yaml/dubbo-consumer
cd /data/k8s-yaml/dubbo-consumer
创建deploy资源清单
cat >dp.yaml <<EOF
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-consumer
namespace: app
labels:
name: dubbo-demo-consumer
spec:
replicas: 1
selector:
matchLabels:
name: dubbo-demo-consumer
template:
metadata:
labels:
app: dubbo-demo-consumer
name: dubbo-demo-consumer
spec:
containers:
- name: dubbo-demo-consumer
image: harbor.od.com/app/dubbo-demo-consumer:master_191201_1800
ports:
- containerPort: 8080
protocol: TCP
- containerPort: 20880
protocol: TCP
env:
- name: JAR_BALL
value: dubbo-client.jar
imagePullPolicy: IfNotPresent
imagePullSecrets:
- name: harbor
restartPolicy: Always
terminationGracePeriodSeconds: 30
securityContext:
runAsUser: 0
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
revisionHistoryLimit: 7
progressDeadlineSeconds: 600
EOF
创建service资源清单
cat >svc.yaml <<EOF
kind: Service
apiVersion: v1
metadata:
name: dubbo-demo-consumer
namespace: app
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 8080
selector:
app: dubbo-demo-consumer
EOF
创建ingress资源清单
cat >ingress.yaml <<EOF
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: dubbo-demo-consumer
namespace: app
spec:
rules:
- host: dubbo-demo.od.com
http:
paths:
- path: /
backend:
serviceName: dubbo-demo-consumer
servicePort: 8080
EOF
创建K8S资源
应用资源配置清单:
kubectl apply -f http://k8s-yaml.od.com/dubbo-consumer/dp.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-consumer/svc.yaml
kubectl apply -f http://k8s-yaml.od.com/dubbo-consumer/ingress.yaml
# 查看容器启动成功没
~]# kubectl get pod -n app
NAME READY STATUS RESTARTS AGE
dubbo-demo-consumer-b8d86bd5b-wbqhs 1/1 Running 0 6s
dubbo-demo-service-79574b6879-cxkls 1/1 Running 0 4h39m
验证启动结果
查看log,是否启动成功:
kubectl -n app logs --tail=2 dubbo-demo-consumer-b8d86bd5b-wbqhs
Dubbo client started
Dubbo 消费者端启动
检查dubbo-monitor是否已经注册成功:
添加dns解析
vi /var/named/od.com.zone
dubbo-demo A 10.4.7.10
# 重启服务
systemctl restart named
# 验证
~]# dig -t A dubbo-demo.od.com @10.4.7.11 +short
10.4.7.10
访问解析
浏览器访问http://dubbo-demo.od.com/hello?name=lg
消费者端源码
提供者端源码
访问地址:dubbo-demo.od.com/hello?name=lg
7.3: 模拟版本升级
接下来我们模拟升级发版,之前已经用同一个镜像打了不同的tag并推送到从库当然正常发版的顺序是:
- 提交修改过的代码的代码块
- 使用jenkins构建新镜像
- 上传到私有harbor仓库中
- 更新de文件并apply
修改dp.yaml资源配置清单
修改harbor镜像仓库中对应的tag版本:
sed -i 's#master_200506_1430#master_200510_1430#g' dp.yaml
应用修改后的资源配置清单
当然也可以在dashboard中进行在线修改:
kubectl apply -f http://k8s-yaml.od.com/dubbo-consumer/dp.yaml
~]# kubectl -n app get pod
NAME READY STATUS RESTARTS AGE
dubbo-demo-consumer-84f75b679c-kdwd7 1/1 Running 0 54s
dubbo-demo-service-79574b6879-cxkls 1/1 Running 0 4h58m
使用浏览器验证
使用浏览器验证:http://dubbo-demo.od.com/hello?name=lg在短暂的超时后,即可正常访问至此,我们一套完成的dubbo服务就已经交付到k8s集群当中了,并且也演示了如何发版。
小结:-----------------
八、实战维护dubbo微服务
8.1: 项目发布
Add_tag 就是check out 的分支,镜像版本名称
在dashboard改拉取的镜像版本
8.2: 项目回滚
8.3: 小结-----------
左边持续集成,右边持续部署
8.4: 宿主机宕机测试
- 当一台宿主机宕,跑在该宿主机的服务将无法访问
- 此时监控软件判断到该宿主机宕了
- 监控触发脚本,kubectl delete node hdss7-21(相当于人为确认该主机宕了)
- K8s集群会自动将宕机节点的服务转移 .
- 前面的10节点上的负载均衡宕机节点也需要注释掉.
- Reload nginx
#宕机的主机恢复后,supervisor会自动开启所有系统服务,
再将标签打上(没什么用)
在宕机节点,开启扩充服务,再将之前转移的服务删掉
#为什么必须删除宕机节点,才能恢复?
宕机节点,k8s集群会认为他是短暂不可达.所以没恢复.
九、集群3个服务小结-------------------
提供者为什么没有svc和ingress资源?没用到,
Zk注册服务相当于dns,消费者找到注册中心,查看有没有helloworld服务,有的话,注册中心会给消费者
服务提供者的pod-ip(snat规则优化用到了,给的源地址),消费者再找到提供者ip,完成服务调用.
如果注册中心注册的不是pod-ip,而是集群ip,则服务提供者会用到svc资源.
Monitor说明问题了(snat规则优化用到了)