本章概述
- 案例一:镜像分层构建
- 案例二:自定义镜像运行Nginx及tomcat服务并基于NFS实现动静分离
- 案例三:自定义镜像结合PV/PVC运行Zookeeper集群
- 案例四:kubernetes运行Redis单机及Redis Cluster
- 案例五:kubernetes基于StatefulSet运行MySQL一主多从
- 案例六:kubernetes运行Jenkins
- 案例七:单Pod多容器实现LNMP并使用MySQL作为SQL服务器
- 案例八:kubernetes基于Zookeeper案例实现微服务动态注册和发现
9.1 案例一:镜像分层构建
9.1.1 分层构建步骤
镜像分层构建流程:
代码部署流程(CI/CD):
具体流程如下:
1、开发写好代码,把代码上传到gitlab
2、jenkins clone代码
3、通过maven把代码编译成jar包或者var包
4、打镜像:把代码打入镜像
5、把构建好的镜像上传到harbor镜像仓库
6、上传完成后,jenkins通过命令或者客户端调用k8s的api接口更新镜像(通过kubectl命令或者在dashboard进行操作)
7、k8s内部对pod进行滚动更新
9.1.2 分层构建镜像
注意:镜像的构建在专用的镜像构建服务器进行,这里没有,在k8s-master1上进行镜像构建
9.1.2.1 构建基础系统镜像
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/{system,web}
mkdir -p /root/k8s-data/dockerfile/system/centos
2、编写Dokcerfile文件(安装基础环境需要的安装包、编译环境,更改时区,删除filebeat源码包等,指定基础镜像为官方centos镜像)
cd /root/k8s-data/dockerfile/system/centos/
下载filebeat-7.12.1-x86_64.rpm安装包
wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.12.1-x86_64.rpm
vim /root/k8s-data/dockerfile/system/centos/Dockerfile
#自定义Centos 基础镜像
FROM centos:7.9.2009
MAINTAINER yuandangsheng "957464230@qq.com"
ADD filebeat-7.12.1-x86_64.rpm /tmp
RUN yum install -y /tmp/filebeat-7.12.1-x86_64.rpm vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop && rm -rf /etc/localtime /tmp/filebeat-7.12.1-x86_64.rpm && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
3、编写构建镜像的脚本
vim /root/k8s-data/dockerfile/system/centos/build-command.sh
#!/bin/bash
docker build -t harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009 . #打镜像
docker push harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009 #把镜像上传到harbor镜像仓库
4、如果harbor镜像仓库没有baseimages仓库,需要先创建baseimages仓库
5、运行脚本,构建镜像,在镜像仓库查看镜像已经上传成功
bash build-command.sh
查看harbor镜像仓库,镜像上传成功
6、基于打好的镜像创建容器,查看是否正常
docker run --rm -it harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009 bash
9.1.2.2 构建服务镜像
第1步:构建基于jdk的镜像
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/pub-images/jdk-1.8.212
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/pub-images/jdk-1.8.212
下载jdk安装包(登录以下网址进行下载)
https://www.oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html
profile文件:
在profile文件中声明变量(可以运行一个tomcat容器,把容器中/etc/profile文件复制出来,把以下内容加载profile文件最后)
vim profile
export JAVA_HOME=/usr/local/jdk
export TOMCAT_HOME=/apps/tomcat
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$TOMCAT_HOME/bin:$PATH
export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
3、编写Dokcerfile文件(安装jdk包,做软连接,加入新的profile文件,声明环境变量,指定基础镜像为9.1.2.1章节已经打好的centos镜像)
cd /root/k8s-data/dockerfile/web/pub-images/jdk-1.8.212
vim Dockerfile
#JDK Base Image
FROM harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009
MAINTAINER yuandangsheng "957464230@qq.com"
ADD jdk-8u212-linux-x64.tar.gz /usr/local/src/
RUN ln -sv /usr/local/src/jdk1.8.0_212 /usr/local/jdk
ADD profile /etc/profile
ENV JAVA_HOME /usr/local/jdk
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/:$JRE_HOME/lib/
ENV PATH $PATH:$JAVA_HOME/bin
4、编写构建镜像的脚本
vim build-command.sh
#!/bin/bash
docker build -t harbor.magedu.local/pub-images/jdk-base:v8.212 .
sleep 1
docker push harbor.magedu.local/pub-images/jdk-base:v8.212
5、创建新的镜像仓库
6、运行脚本,构建镜像,在harbor查看镜像,是否上传成功
bash build-command.sh
查看harbor镜像仓库,镜像上传成功
第2步:构建基于nginx的服务镜像
注意:该镜像只对nginx做了编译,无法根据该镜像运行容器,还需要添加配置文件以及守护进程
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/pub-images/nginx-base
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/pub-images/nginx-base
下载nginx安装包
wget http://nginx.org/download/nginx-1.20.2.tar.gz
3、编写Dokcerfile文件(安装基础环境安装包,对nginx进行编译,做软连接,删除nginx源码包,#指定基础镜像为9.1.2.1章节已经打好的centos镜像)
cd /root/k8s-data/dockerfile/web/pub-images/nginx-base
vim Dockerfile
#Nginx Base Image
FROM harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009
MAINTAINER yuandangsheng "957464230@qq.com"
RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
ADD nginx-1.20.2.tar.gz /usr/local/src/
RUN cd /usr/local/src/nginx-1.20.2 && ./configure && make && make install && ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx &&rm -rf /usr/local/src/nginx-1.20.2.tar.gz
4、编写构建镜像的脚本
vim build-command.sh
#!/bin/bash
docker build -t harbor.magedu.local/pub-images/nginx-base:v1.20.2 .
sleep 1
docker push harbor.magedu.local/pub-images/nginx-base:v1.20.2
5、运行脚本,构建镜像,在harbor查看镜像,是否上传成功
bash build-command.sh
查看harbor镜像仓库,镜像上传成功
第3步:构建基于jdk的tomcat镜像
注意:该镜像只指定tomcat配置文件、默认web页面路径,并且添加源码包,没有添加配置文件无法根据该镜像运行容器,还需要添加配置文件以及守护进程
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/pub-images/tomcat-base-8.5.43
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/pub-images/tomcat-base-8.5.43
下载tomcat安装包
wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.43/bin/apache-tomcat-8.5.43.tar.gz
3、编写Dokcerfile文件(创建tomcat普通用户,做软连接,更改tomcat配置文件权限,#指定基础镜像为9.1.2.2.1章节已经打好的jdk镜像)
cd /root/k8s-data/dockerfile/web/pub-images/tomcat-base-8.5.43
vim Dockerfile
#Tomcat 8.5.43基础镜像
FROM harbor.magedu.local/pub-images/jdk-base:v8.212
MAINTAINER yuandangsheng "957464230@qq.com"
RUN mkdir /apps /data/tomcat/webapps /data/tomcat/logs -pv
ADD apache-tomcat-8.5.43.tar.gz /apps
RUN useradd tomcat -u 2050 && ln -sv /apps/apache-tomcat-8.5.43 /apps/tomcat && chown -R tomcat.tomcat /apps /data
4、编写构建镜像的脚本
vim build-command.sh
#!/bin/bash
docker build -t harbor.magedu.local/pub-images/tomcat-base:v8.5.43 .
sleep 3
docker push harbor.magedu.local/pub-images/tomcat-base:v8.5.43
5、运行脚本,构建镜像,在harbor查看镜像,是否上传成功
bash build-command.sh
查看harbor镜像仓库,镜像上传成功
6、根据新构建的镜像创建容器,查看运行环境是否已经具备
docker run --rm -it harbor.magedu.local/pub-images/tomcat-base:v8.5.43 bash
# /apps/tomcat/bin/catalina.sh run
查看data目录权限,属主和属组是否为tomcat
9.1.2.3 构建业务镜像
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/tomcat-app1
2、准备Dockerfile需要的文件(catalina.sh和server.xml可以通过创建一个临时的tomcat容器,然后从容器中复制出来,然后再修改)
cd /root/k8s-data/dockerfile/web/magedu/tomcat-app1
(1)准备catalina.sh,添加以下启动参数
JAVA_OPTS="-server -Xms1g -Xmx1g -Xss512k -Xmn1g -XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2 -XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled"
(2)准备server.xml,更改存放代码的目录为/data/tomcat/webapps
<Host name="localhost" appBase="/data/tomcat/webapps" unpackWARs="false" autoDeploy="false">
(3)准备代码文件app1.tar.gz(测试页)
mkdir myapp -p
cd myapp
vim index.html
<h1>tomcat app1 for linux n66</h1>
tar -zcvf app1.tar.gz ./index.html
cd /root/k8s-data/dockerfile/web/magedu/tomcat-app1
mv myapp/app1.tar.gz ./
(4)准备tomcat启动脚本
cd /root/k8s-data/dockerfile/web/magedu/tomcat-app1
vim run_tomcat.sh
#!/bin/bash
su - tomcat -c "/apps/tomcat/bin/catalina.sh start" #以tomcat用户启动服务
tail -f /etc/hosts #指定tomcat容器PID为1的守护进程
3、编写Dokcerfile文件(安装jdk包,做软连接,加入新的profile文件,声明环境变量)
cd /root/k8s-data/dockerfile/web/magedu/tomcat-app1
vim Dockerfile
#tomcat web1
FROM harbor.magedu.local/pub-images/tomcat-base:v8.5.43
ADD catalina.sh /apps/tomcat/bin/catalina.sh #加载catalina.sh
ADD server.xml /apps/tomcat/conf/server.xml #加载server.xml
ADD app1.tar.gz /data/tomcat/webapps/myapp/ #加载测试页面
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh #加载tomcat启动脚本
RUN chown -R tomcat.tomcat /data/ /apps/ #更改tomcat配置文件权限
EXPOSE 8080 8443
CMD ["/apps/tomcat/bin/run_tomcat.sh"] #指定tomcat启动脚本
4、编写构建镜像的脚本
vim build-command.sh
build-command.sh
#!/bin/bash
TAG=$1 #通过位置变量传递参数来指定构建镜像的版本
docker build -t harbor.magedu.local/magedu/tomcat-app1:${TAG} .
sleep 3
docker push harbor.magedu.local/magedu/tomcat-app1:${TAG}
5、创建新的镜像仓库
6、运行脚本,构建镜像,在harbor查看镜像,是否上传成功
bash build-command.sh 20220506_183905
注意,这里需要在运行脚本命令后输入位置变量传参,来指定构建镜像的版本,为了便于区分,可以用时间戳作为版本
7、通过指定新构建的镜像创建容器,验证镜像是否可用
docker run --rm -it -p 8080:8080 harbor.magedu.local/magedu/tomcat-app1:20220506_183905
在浏览器输入172.31.7.101:8080/myapp
验证通过,可以将该镜像在k8s集群内创建容器,提供服务
9.1.2.4 K8S集群运行业务容器
1、创建存放yaml文件的路径(为了便于区分,该路径最好和dockerfile路径相对应)
mkdir -p /root/k8s-data/yaml/magedu/tomcat-app1
2、编写yaml文件
vim tomcat-app1.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app1-deployment-label
name: magedu-tomcat-app1-deployment
namespace: magedu
spec:
replicas: 2 #指定副本数
selector:
matchLabels:
app: magedu-tomcat-app1-selector
template:
metadata:
labels:
app: magedu-tomcat-app1-selector
spec:
containers:
- name: magedu-tomcat-app1-container
image: harbor.magedu.local/magedu/tomcat-app1:20220506_183905 #指定创建容器的镜像为9.1.2.3章节构建的镜像
imagePullPolicy: IfNotPresent
ports: #指定端口
- containerPort: 8080
protocol: TCP
name: http
env: #传入环境变量
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources: #资源限制
limits:
cpu: 1
memory: "512Mi"
requests:
cpu: 500m
memory: "512Mi"
volumeMounts:
- name: magedu-images
mountPath: /usr/local/nginx/html/webapp/images
readOnly: false
- name: magedu-static
mountPath: /usr/local/nginx/html/webapp/static
readOnly: false
volumes:
- name: magedu-images
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/images
- name: magedu-static
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/static
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-tomcat-app1-service-label
name: magedu-tomcat-app1-service
namespace: magedu
spec:
type: NodePort #指定网络类型
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 30092 #暴露宿主机端口供外部访问,该端口是用于测试tomcat服务是否可用,在测试完成后,要将该端口注释掉,tomcat不需要向外部暴露端口
selector:
app: magedu-tomcat-app1-selector
创建namespace magedu
kubectl create ns magedu
创建pod
kubectl apply -f tomcat-app1.yaml
查看pod
查看pod日志,pod已经成功运行
访问web页面进行验证
这样基于tomcat服务的业务容器就已经运行起来了。
9.2 案例二:自定义镜像运行Nginx及tomcat服务并基于NFS实现动静分离
Nginx+Tomcat+NFS实现动静分离架构图:
注意:由于tomcat已经在9.1.2.4章节部署完成,这里直接引用,不再重新部署
9.2.1 部署nginx
由于nginx服务镜像在9.1.2.2.2已经构建完成,只需要基于该镜像构建nginx的业务镜像即可
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/nginx
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/magedu/nginx
(1)准备nginx.conf配置文件
vim nginx.conf
user tomcat tomcat; #指定tomcat用户,为了和后端服务器保持用户一致,这里使用tomcat用户作为nginx用户
#在http代码段中添加以下内容
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /webapp { #静态文件请求,即/webapp路径的请求nginx本地进行处理
root html;
index index.html index.htm;
}
location /myapp { #动态文件请求,即/myapp路径的请求转发给tomcat处理
proxy_pass http://tomcat_webserver;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
upstream tomcat_webserver { #配置后端tomcat_webserver
server magedu-tomcat-app1-service.magedu.svc.magedu.local:80; #指定tomcat service name,使nginx可以把动态请求转发给tomcat
}
注意:tomcat的service name通过kubectl get svc -n magedu获取,service全称为magedu-tomcat-app1-service.magedu.svc.magedu.local
(2)准备index.html
vim index.html
<h1>nginx web1 magedu n66 v1 </h1>
(3)准备app1.tar.gz(测试页面)
mkdir -p webapp
cd webapp
vim index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Devops</title>
</head>
<body>
<h1>magedu devops v11111111</h1>
</body>
</html>
tar -czvf ./index.html app1.tar.gz
cd /root/k8s-data/dockerfile/web/magedu/nginx
mv webapp/app1.tar.gz ./
3、编写Dokcerfile文件(添加nginx配置文件和web页面,更改配置文件权限,#指定基础镜像为9.1.2.2.2已经构建好的镜像)
cd /root/k8s-data/dockerfile/web/pub-images/nginx-base
vim Dockerfile
#Nginx 1.20.2
FROM harbor.magedu.local/pub-images/nginx-base:v1.20.2
RUN useradd tomcat -u 2050 #创建用户
ADD nginx.conf /usr/local/nginx/conf/nginx.conf #加载nginx配置文件
ADD app1.tar.gz /usr/local/nginx/html/webapp/ #加载nginx代码
ADD index.html /usr/local/nginx/html/index.html #加载nginx 主web页面
#静态资源挂载路径
RUN mkdir -p /usr/local/nginx/html/webapp/static /usr/local/nginx/html/webapp/images && chown tomcat.tomcat -R /usr/local/nginx/html/webapp/static /usr/local/nginx/html/webapp/images
EXPOSE 80 443
CMD ["nginx"]
4、编写构建镜像的脚本
vim build-command.sh
#!/bin/bash
TAG=$1 #通过位置变量传递参数来指定构建镜像的版本
docker build -t harbor.magedu.local/magedu/nginx-web1:${TAG} .
echo "镜像构建完成,即将上传到harbor"
sleep 1
docker push harbor.magedu.local/magedu/nginx-web1:${TAG}
echo "镜像上传到harbor完成"
5、运行脚本,构建镜像,在harbor查看镜像,是否上传成功
bash build-command.sh 20220507_094530 #注意,这里需要在运行脚本命令后输入位置变量传参,来指定构建镜像的版本,为了便于区分,可以用时间戳作为版本
查看harbor镜像仓库,镜像上传成功
使用新构建的业务镜像,创建并进入容器,查看是否可以正常运行
docker run --rm -it harbor.magedu.local/magedu/nginx-web1:20220507_094530 bash
(1)进入容器后查看是否存在tomcat用户
cat /etc/passwd
(2)查看nginx配置文件内容是否预期的一致
cat /usr/local/nginx/conf/nginx.conf
(3)查看nginx配置文件属组和属主是否为tomcat
ls -lhd /usr/local/nginx/html/webapp/static /usr/local/nginx/html/webapp/images
6、在k8s集群部署nginx
(1)创建存放yaml文件的目录
mkdir -p /root/k8s-data/yaml/web/magedu/nginx
(2)编辑nginx yaml文件
cd /root/k8s-data/yaml/web/magedu/nginx
vim nginx.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
app: magedu-nginx-deployment-label
name: magedu-nginx-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-nginx-selector
template:
metadata:
labels:
app: magedu-nginx-selector
spec:
containers:
- name: magedu-nginx-container
image: harbor.magedu.local/magedu/nginx-web1:20220507_094530 #指定镜像为上面已经构建好的业务镜像
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
- containerPort: 443
protocol: TCP
name: https
env:
- name: "password"
value: "123456"
- name: "age"
value: "20"
resources:
limits:
cpu: 500m
memory: 500Mi
requests:
cpu: 500m
memory: 500Mi
volumeMounts:
- name: magedu-images #指定存储卷在容器内的挂载路径
mountPath: /usr/local/nginx/html/webapp/images
readOnly: false
- name: magedu-static #指定存储卷在容器内的挂载路径
mountPath: /usr/local/nginx/html/webapp/static
readOnly: false
volumes:
- name: magedu-images
nfs: #指定nfs挂载路径
server: 172.31.7.109
path: /data/k8sdata/magedu/images
- name: magedu-static
nfs: #指定nfs挂载路径
server: 172.31.7.109
path: /data/k8sdata/magedu/static
#nodeSelector:
# group: magedu
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-nginx-service-label
name: magedu-nginx-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
nodePort: 30090 #指定宿主机http暴露端口
- name: https
port: 443
protocol: TCP
targetPort: 443
nodePort: 30091 #指定宿主机https暴露端口
selector:
app: magedu-nginx-selector
(3)登录nfs存储服务器172.31.7.109
创建挂载目录
cd /data/k8sdata
mkdir -p magedu/{iamges,static}
更改配置文件,添加挂载目录,赋予读写权限
vim /etc/exports
/data/k8sdata/magedu *(rw,no_root_squash)
重启nfs,使配置生效
systemctl restart nfs-server
(4)在172.31.7.101节点上
创建pod
cd /root/k8s-data/yaml/web/magedu/nginx
kubectl apply -f nginx.yaml
查看pod
(5)访问web页面测试
访问nginx默认页面http://172.31.7.112:30090
访问nginx静态文件测试页面http://172.31.7.112:30090/webapp
7、配置负载均衡和域名解析
(1)为了便于访问,在前端添加负载均衡器(以haproxy为例)
在172.31.7.104节点更改haproxy配置文件(172.31.7.189是通过keepalived服务做的VIP地址,具体请参考3.2.1章节)
vim /etc/haproxy/haprox.cfg
listen magedu-linux66-nginx-80
bind 172.31.7.189:80
mode tcp
server node1 172.31.7.111:30090 check inter 3s fall 3 rise 1
server node2 172.31.7.112:30090 check inter 3s fall 3 rise 1
server node3 172.31.7.113:30090 check inter 3s fall 3 rise 1
listen magedu-linux66-nginx-443
bind 172.31.7.189:443
mode tcp
server node1 172.31.7.111:30091 check inter 3s fall 3 rise 1
server node2 172.31.7.112:30091 check inter 3s fall 3 rise 1
server node3 172.31.7.113:30091 check inter 3s fall 3 rise 1
(2)重启haproxy使配置生效
systemctl restart haproxy
(3)通过访问VIP地址172.31.7.189进行测试
(4)为了方便,在本地添加域名解析,把172.31.7.189和www.mysite.com绑定
(5)访问www.mysite.com 为nginx主页面
访问www.mysite.com/webapp是静态页面,nginx本地处理
访问www.mysite.com/myapp,会转发给tomcat
(6)转发效果:
nginx向tomcat转发是轮询方式,为了查看转发效果,更改其中一个tomcat的测试页面内容
在172.31.7.101节点上进入其中一个tomcat容器
kubectl exec -it magedu-tomcat-app1-deployment-576cbfd679-pns7z bash -n magedu
更改默认页面内容
vim /data/tomcat/webapps/myapp/index.html
<h1>tomcat app1 for linux n66 v2</h1>
然后再次访问tomcat,可以发现两次访问的内容并不相同,说明nginx的轮询转发已生效
第一次访问:
第二次访问:
(7)后端服务器生成图片验证动静分离:
由于tomcat容器和nginx容器挂载的nfs存储路径一样,在tomcat容器上两个挂载目录下存放不同的文件模拟静态文件和动态文件
进入tomcat容器,在挂载目录/usr/local/nginx/html/webapp/static添加图片模拟静态文件,在在挂载目录/usr/local/nginx/html/webapp/iamges添加js文件模拟动态文件
访问静态图片
访问js文件
如何更新代码
1、更改镜像文件,把开发给的代码文件,重新打入镜像,构建新的镜像包
(1)手动修改nginx首页内容
(2)重新打镜像,运行构建镜像脚本 bash build-command.sh
2、镜像构建完成后,修改yaml文件中镜像版本
(1)手动修改yaml文件中常见pod需要的镜像版本
3、重新加载yaml文件
(1)kubectl apply -f xx.yaml
4、pod会被重建,k8s集群会自动进行滚动更新
9.3 案例三:自定义镜像结合PV/PVC运行Zookeeper集群
架构图:
zookeeper访问流程(生产者/消费者模型):
服务端为生产者,即provider
客户端为消费者,即consumer
1.服务端在配置文件中指定配置中心地址,当服务端运行时会将服务端地址上报给注册中心
2.客户端同时也配置注册中心地址,从注册中心获取服务端地址
3.客户端根据从注册中心获取的地址,直接访问服务端,这样就大大节省了访问流程,能提高效率。
4.一旦服务端某个节点宕机,注册中心会及时发现,并告知客户端,客户端将不会再请求已经宕机的服务节点。
9.3.1 构建镜像
由于zookeeper需要java环境,需要先构建jdk镜像,在9.1.2.2.1章节我们已经构建的jdk基础镜像可以使用,但由于自己打的镜像包过大,此次示例使用docker官方镜像仓库下载的镜像。
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/zookeeper
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/magedu/zookeeper
(1)下载docker官方jdk镜像,上传到harbor私有仓库,可以加快构建速度。
docker pull docker pull elevy/slim_java:8
docker tag elevy/slim_java:8 harbor.magedu.local/magedu/slim_java:8
docker push harbor.magedu.local/magedu/slim_java:8
(2)准备国内镜像源,能够更快的构建进行
vim repositories
http://mirrors.aliyun.com/alpine/v3.6/main
http://mirrors.aliyun.com/alpine/v3.6/community
(3)下载zookeeper源码包
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz.asc
(4)准备zookeeper配置文件
conf文件:
mkdir /root/k8s-data/dockerfile/web/magedu/zookeeper/conf
cd /root/k8s-data/dockerfile/web/magedu/zookeeper/conf
vim zoo.cfg
tickTime=2000 #心跳检测时间,单位是毫秒,即2s进行一次心跳检测
initLimit=10 #zk初始化周期,单位是次,该时间为initLimit* tickTime,即10*2000ms,如果在20s内没有初始化成功,则会被认为失败
syncLimit=5 #zk同步周期,单位是次,该时间为syncLimit * tickTime,即5*2000ms,如果在10s内没有同步成功,则会被认为失败
dataDir=/zookeeper/data #zk数据目录
dataLogDir=/zookeeper/wal #zk日志目录
#snapCount=100000
autopurge.purgeInterval=1
clientPort=2181 #指定端口
quorumListenOnAllIPs=true
bin文件:
mkdir /root/k8s-data/dockerfile/web/magedu/zookeeper/bin
cd /root/k8s-data/dockerfile/web/magedu/zookeeper/bin
vim bin/zkReady.sh
#!/bin/bash
/zookeeper/bin/zkServer.sh status | egrep 'Mode: (standalone|leading|following|observing)'
(5)部署zookeeper集群需要在每个节点的配置文件中添加每个节点的myid、ip地址、端口等,这里我们通过脚本动态生成。脚本内容如下:
cd /opt/skywalking-dubbo_2.5.3-k8s-data_dockerfile-yaml/dockerfile/web/myserver/zookeeper
vim entrypoint.sh
#!/bin/bash
echo ${MYID:-1} > /zookeeper/data/myid #添加myid,要添加到zk数据目录中
if [ -n "$SERVERS" ]; then #添加ip地址和端口
IFS=\, read -a servers <<<"$SERVERS"
for i in "${!servers[@]}"; do
printf "\nserver.%i=%s:2888:3888" "$((1 + $i))" "${servers[$i]}" >> /zookeeper/conf/zoo.cfg
done
fi
cd /zookeeper
exec "$@"
注意:上面脚本中的变量MYID和SERVERS,在zookeeper.yaml文件中定义,是通过yaml文件构建容器时获取的
3、编写Dokcerfile文件(父镜像为官网java基础镜像)
cd /root/k8s-data/dockerfile/web/magedu/zookeeper
vim Dockerfile
#FROM harbor-linux38.local.com/linux38/slim_java:8
FROM harbor.magedu.local/magedu/slim_java:8
ENV ZK_VERSION 3.4.14 #指定zk版本
ADD repositories /etc/apk/repositories #添加国内镜像源,能够更快的下载镜像
# Download Zookeeper
COPY zookeeper-3.4.14.tar.gz /tmp/zk.tgz #加载zk安装包
COPY zookeeper-3.4.14.tar.gz.asc /tmp/zk.tgz.asc #加载zk源码包
COPY KEYS /tmp/KEYS #加载key文件
RUN apk add --no-cache --virtual .build-deps \ #安装常用的命令工具
ca-certificates \
gnupg \
tar \
wget && \
#
# Install dependencies
apk add --no-cache \
bash && \
#
#
# Verify the signature
export GNUPGHOME="$(mktemp -d)" && \
gpg -q --batch --import /tmp/KEYS && \
gpg -q --batch --no-auto-key-retrieve --verify /tmp/zk.tgz.asc /tmp/zk.tgz && \
#
# Set up directories
#
mkdir -p /zookeeper/data /zookeeper/wal /zookeeper/log && \ #创建zk数据目录、日志目录等
#
# Install
tar -x -C /zookeeper --strip-components=1 --no-same-owner -f /tmp/zk.tgz && \
#
# Slim down
cd /zookeeper && \
cp dist-maven/zookeeper-${ZK_VERSION}.jar . && \ #删除不常用的数据文件
rm -rf \
*.txt \
*.xml \
bin/README.txt \
bin/*.cmd \
conf/* \
contrib \
dist-maven \
docs \
lib/*.txt \
lib/cobertura \
lib/jdiff \
recipes \
src \
zookeeper-*.asc \
zookeeper-*.md5 \
zookeeper-*.sha1 && \
#
# Clean up
apk del .build-deps && \
rm -rf /tmp/* "$GNUPGHOME"
COPY conf /zookeeper/conf/ #加载配置文件
COPY bin/zkReady.sh /zookeeper/bin/ #加载zk
COPY entrypoint.sh /
ENV PATH=/zookeeper/bin:${PATH} \
ZOO_LOG_DIR=/zookeeper/log \
ZOO_LOG4J_PROP="INFO, CONSOLE, ROLLINGFILE" \
JMXPORT=9010
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "zkServer.sh", "start-foreground" ] #为/entrypoint.sh脚本传参
EXPOSE 2181 2888 3888 9010
4、编写构建镜像的脚本
vim build-command.sh
#!/bin/bash
TAG=$1
docker build -t harbor.magedu.local/magedu/zookeeper:${TAG} .
sleep 1
docker push harbor.magedu.local/magedu/zookeeper:${TAG}
5、运行脚本,构建镜像
bash build-command.sh v3.4.14 #指定镜像版本为v3.4.14
通过手动拉起容器进行验证
docker run -it --rm harbor.magedu.local/magedu/zookeeper:v3.4.14
9.3.2 创建pv/pvc
1、在nfs存储(172.31.7.109)上创建挂载目录
mkdir -p /data/k8sdata/magedu/zookeeper-datadir-1
mkdir -p /data/k8sdata/magedu/zookeeper-datadir-2
mkdir -p /data/k8sdata/magedu/zookeeper-datadir-3
注意:由于nfs配置文件中/etc/exports中/data/k8sdata/magedu已经做过配置,这里可以直接使用,如果使用的挂载路径没有使用过,这里需要在/etc/exprots中进行配置
2、在master1节点创建存放文件目录
mkdir -p /root/k8s-data/yaml/magedu/zookeeper/pv
cd /root/k8s-data/yaml/magedu/zookeeper/pv
3、编写yaml文件
(1)创建pv
vim zookeeper-persistentvolume.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: zookeeper-datadir-pv-1
spec:
capacity:
storage: 20Gi
accessModes: #指定访问权限
- ReadWriteOnce
nfs: #指定挂载路径
server: 172.31.7.109
path: /data/k8sdata/magedu/zookeeper-datadir-1
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: zookeeper-datadir-pv-2
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/zookeeper-datadir-2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: zookeeper-datadir-pv-3
spec:
capacity:
storage: 20Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/zookeeper-datadir-3
在master1上执行命令创建pv
kubectl apply -f zookeeper-persistentvolume.yaml
查看pv:kubectl get pv
(2)创建pvc
cd /root/k8s-data/yaml/magedu/zookeeper/pv
vim zookeeper-persistentvolumeclaim.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zookeeper-datadir-pvc-1
namespace: magedu
spec:
accessModes:
- ReadWriteOnce
volumeName: zookeeper-datadir-pv-1
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zookeeper-datadir-pvc-2
namespace: magedu
spec:
accessModes:
- ReadWriteOnce
volumeName: zookeeper-datadir-pv-2
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zookeeper-datadir-pvc-3
namespace: magedu
spec:
accessModes:
- ReadWriteOnce
volumeName: zookeeper-datadir-pv-3
resources:
requests:
storage: 10Gi
创建pvc
kubectl apply -f zookeeper-persistentvolumeclaim.yaml
查看pvc
9.3.3 K8S部署zookeeper集群
在k8s集群部署zookeeper集群(由于zookeeper集群要有三个节点,通过deployment控制器进行创建)
1、创建存放yaml文件的目录
mkdir -p /root/k8s-data/yaml/magedu/zookeeper
2、编辑yaml文件
cd /root/k8s-data/yaml/magedu/zookeeper
vim zookeeper.yaml
apiVersion: v1
kind: Service
metadata:
name: zookeeper
namespace: magedu
spec:
ports:
- name: client
port: 2181
selector:
app: zookeeper
---
apiVersion: v1
kind: Service
metadata:
name: zookeeper1
namespace: magedu
spec:
type: NodePort
ports: #暴漏zk端口,便于k8s集群外部服务调用zk
- name: client
port: 2181
nodePort: 32181
- name: followers
port: 2888
- name: election
port: 3888
selector:
app: zookeeper
server-id: "1"
---
apiVersion: v1
kind: Service
metadata:
name: zookeeper2
namespace: magedu
spec:
type: NodePort
ports:
- name: client
port: 2181
nodePort: 32182
- name: followers
port: 2888
- name: election
port: 3888
selector:
app: zookeeper
server-id: "2"
---
apiVersion: v1
kind: Service
metadata:
name: zookeeper3
namespace: magedu
spec:
type: NodePort
ports:
- name: client
port: 2181
nodePort: 32183
- name: followers
port: 2888
- name: election
port: 3888
selector:
app: zookeeper
server-id: "3"
---
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
name: zookeeper1
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: zookeeper
template:
metadata:
labels:
app: zookeeper
server-id: "1"
spec:
volumes:
- name: data
emptyDir: {}
- name: wal
emptyDir:
medium: Memory
containers:
- name: server
image: harbor.magedu.local/magedu/zookeeper:v3.4.14 #指定镜像
imagePullPolicy: Always
env: #传参,该参数为entrypoint.sh脚本中的参数
- name: MYID
value: "1"
- name: SERVERS
value: "zookeeper1,zookeeper2,zookeeper3"
- name: JVMFLAGS
value: "-Xmx2G"
ports:
- containerPort: 2181 #对client使用的端口
- containerPort: 2888 #集群内机器通讯使用端口
- containerPort: 3888 #选举leader使用端口
volumeMounts:
- mountPath: "/zookeeper/data"
name: zookeeper-datadir-pvc-1
volumes:
- name: zookeeper-datadir-pvc-1
persistentVolumeClaim:
claimName: zookeeper-datadir-pvc-1
---
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
name: zookeeper2
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: zookeeper
template:
metadata:
labels:
app: zookeeper
server-id: "2"
spec:
volumes:
- name: data
emptyDir: {}
- name: wal
emptyDir:
medium: Memory
containers:
- name: server
image: harbor.magedu.local/magedu/zookeeper:v3.4.14
imagePullPolicy: Always
env:
- name: MYID
value: "2"
- name: SERVERS
value: "zookeeper1,zookeeper2,zookeeper3"
- name: JVMFLAGS
value: "-Xmx2G"
ports:
- containerPort: 2181
- containerPort: 2888
- containerPort: 3888
volumeMounts:
- mountPath: "/zookeeper/data"
name: zookeeper-datadir-pvc-2
volumes:
- name: zookeeper-datadir-pvc-2
persistentVolumeClaim:
claimName: zookeeper-datadir-pvc-2
---
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
name: zookeeper3
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: zookeeper
template:
metadata:
labels:
app: zookeeper
server-id: "3"
spec:
volumes:
- name: data
emptyDir: {}
- name: wal
emptyDir:
medium: Memory
containers:
- name: server
image: harbor.magedu.local/magedu/zookeeper:v3.4.14
imagePullPolicy: Always
env:
- name: MYID
value: "3"
- name: SERVERS
value: "zookeeper1,zookeeper2,zookeeper3"
- name: JVMFLAGS
value: "-Xmx2G"
ports:
- containerPort: 2181
- containerPort: 2888
- containerPort: 3888
volumeMounts:
- mountPath: "/zookeeper/data"
name: zookeeper-datadir-pvc-3
volumes:
- name: zookeeper-datadir-pvc-3
persistentVolumeClaim:
claimName: zookeeper-datadir-pvc-3
3、部署zookeeper集群
kubectl apply -f zookeeper.yaml
4、验证zk集群(一个leader,两个follower)
(1)进入容器查看zookeeper1的状态为follower
kubectl exec -it zookeeper1-587796b544-z7zf9 bash -n magedu
/zookeeper/bin/zkServer.sh status
(2)进入容器查看zookeeper2的状态为leader
kubectl exec -it zookeeper2-6cbdc4ff9f-bts6q bash -n magedu
/zookeeper/bin/zkServer.sh status
(3)进入容器查看zookeeper2的状态为follower
kubectl exec -it zookeeper3-86d59786b-987cz bash -n magedu
/zookeeper/bin/zkServer.sh status
5、可以发现三个zookeeper节点,zookeeper1和zookeeper3是follower,zookeeper2是leader。
zookeeper选举机制
1、当我们部署zookeeper集群时,leader节点大部分是zookeeper2或者zookeeper3节点,很少是zookeeper1节点,原因如下:
首选要明确zookeeper集群leader选举的条件:
(1)过半机制,即集群内节点要超过集群节点总数的一般以上才会进行leader选举(如集群3节点,要有两个节点准备完毕才会进行选举)
(2)选举条件:比对集群节点的事务id和节点id(MYID),会先比对事务id,再比对节点id。
注意:事务id类似于mysql的binlog,记录了zookeeper数据位置,一旦集群数据有变动,事务id就会更新,哪个节点记录的数据与当前数据最接近,哪个节点的事务id最大。
2、zookeeper集群第一次部署时的选举过程:
(1)在集群进行初始化时,如果集群节点初始化较慢
当zookeeper1初始化完成后,只有一个节点,不满足过半机制,不进行leader选举;
当zookeeper1和zookeeper2初始化完成后,满足过半机制,进行leader选举;由于集群刚初始化完成,集群内没有数据,因此两个节点的事务id一致;然后比对两个节点的节点id(即myid),由于zookeeper2比zookeeper1的myid大,因此zookeeper2被选举为leader;
当三个节点全部初始化完成,此时zookeeper2已经作为集群的leader,则zookeeper3会成为集群的follower角色加入集群。
(2)如果集群节点拉起较快,三个节点同时被拉起,通过以上规则,zookeeper3会被选举为leader
zookeeper集群运行一段时间后选举:
比对各个节点的事务id,哪个节点的事务id记录的数据最新,则哪个节点的数据最全,那么该节点就会被选举为leader,如果事务id一样,则会再比较节点id(MYID),哪个节点的MYID最大,则哪个节点被选举为leader
查看zookeeper节点上的配置文件,在每个配置文件最后三行都已经加上了每个节点的节点id、servicename(servicename会解析为serviceIP,然后把请求转发给后端的zk容器)和端口,这个zookeeper集群每个节点必须配置的,这个配置是构建镜像时entrypoint.sh脚本动态生成的。
3、验证选举机制:
(1)删除当前集群的leader,即zookeeper2
kubectl delete pod zookeeper2-6cbdc4ff9f-bts6q -n magedu
(2)此时zookeeper3节点被选举为集群leader(由于集群刚部署完,没有数据写入,事务id一致,比对节点id,zookeeper3的节点id最大,zookeeper3被选举为leader)
(3)当zookeeper2被重建出来后,由于zookeeper3已经被选举为leader,zookeeper2会以follower的角色加入集群。
9.4 案例四:kubernetes运行Redis单机及Redis Cluster
9.4.1 构建镜像
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/redis
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/magedu/redis
(1)下载安装包
官网链接:https://redis.io/download/
wget https://download.redis.io/releases/redis-4.0.14.tar.gz
(2)准备配置文件redis.conf
vim redis.conf
bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile ""
databases 16
always-show-logo yes
save 900 1 #设置快照的时间
save 5 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data/redis-data #指定redis数据目录
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
requirepass 123456 #设置密码,防止被人恶意链接redis
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
appendonly yes #开启aof备份
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
aof-use-rdb-preamble no
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
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
aof-rewrite-incremental-fsync yes
(3)准备redis运行脚本
vim run_redis.sh
#!/bin/bash
/usr/sbin/redis-server /usr/local/redis/redis.conf
tail -f /etc/hosts
3、编写Dockerfile(使用centos基础镜像作为父镜像,即9.1.2.1章节构建的镜像)
vim Dockerfile
#Redis Image
FROM harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009
MAINTAINER zhangshijie "zhangshijie@magedu.net"
ADD redis-4.0.14.tar.gz /usr/local/src
RUN ln -sv /usr/local/src/redis-4.0.14 /usr/local/redis && cd /usr/local/redis && make && cp src/redis-cli /usr/sbin/ && cp src/redis-server /usr/sbin/ && mkdir -pv /data/redis-data
ADD redis.conf /usr/local/redis/redis.conf
ADD run_redis.sh /usr/local/redis/run_redis.sh
EXPOSE 6379
CMD ["/usr/local/redis/run_redis.sh"]
4、编写构建镜像的脚本
vim build-command.sh
#!/bin/bash
TAG=$1
docker build -t harbor.magedu.local/magedu/redis:${TAG} .
sleep 3
docker push harbor.magedu.local/magedu/redis:${TAG}
5、运行脚本,构建镜像
bash build-command.sh 4.0.14
6、验证通过镜像是否可以拉起容器:
docker run --rm -it -p 6379:6379 harbor.magedu.local/magedu/redis:4.0.14
9.4.2 创建pv/pvc
1、在nfs存储(172.31.7.109)上创建挂载目录
mkdir -p /data/k8sdata/magedu/redis-datadir-1
注意:由于nfs配置文件中/etc/exports中/data/k8sdata/magedu已经做过配置,这里可以直接使用,如果使用的挂载路径没有使用过,这里需要在/etc/exprots中进行配置
2、在master1节点创建存放文件目录
mkdir -p /root/k8s-data/yaml/magedu/redis/pv
cd /root/k8s-data/yaml/magedu/redis/pv
3、编写yaml文件
(1)创建pv
vim redis-persistentvolume.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-datadir-pv-1
namespace: magedu
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/k8sdata/magedu/redis-datadir-1
server: 172.31.7.109
创建pv
kubectl apply -f redis-persistentvolume.yaml
查看pv
(2)创建pvc
vim redis-persistentvolumeclaim.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: redis-datadir-pvc-1
namespace: magedu
spec:
volumeName: redis-datadir-pv-1
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
创建pvc
kubectl apply -f redis-persistentvolumeclaim.yaml
查看pvc
9.4.3 K8S部署redis(单机)
1、创建存放yaml文件的目录
mkdir -p /root/k8s-data/yaml/magedu/redis
2、编辑redis yaml文件
cd /root/k8s-data/yaml/magedu/zookeeper
vim redis.yaml
redis.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: devops-redis
name: deploy-devops-redis
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: devops-redis
template:
metadata:
labels:
app: devops-redis
spec:
containers:
- name: redis-container
image: harbor.magedu.local/magedu/redis:4.0.14
imagePullPolicy: Always
volumeMounts:
- mountPath: "/data/redis-data/" #挂载路径为redis数据目录,在配置文件中指定
name: redis-datadir
volumes:
- name: redis-datadir
persistentVolumeClaim:
claimName: redis-datadir-pvc-1
---
kind: Service
apiVersion: v1
metadata:
labels:
app: devops-redis
name: srv-devops-redis
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 6379
targetPort: 6379
nodePort: 36379 #如果k8s集群外部服务需要访问redis,则暴露端口,如果没有,则无需暴露端口
selector:
app: devops-redis
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
3、创建redis
kubectl apply -f redis.yaml
4、查看pod,在172.31.7.113上
5、访问验证(本地访问、集群内部访问、集群外部访问)
(1)本地访问:进入容器访问
(2)集群内部访问:
注意:在集群内部访问,只需访问redis的servicename和6379端口
查看redis的service
在k8s集群内部进入同一namespace下的容器中(如果不在同一namespace,访问时需要加入namespace名称)
(3)远程访问:访问容器所在宿主机的ip和暴露的nodeport,即36379端口
(4)验证redis备份(同时开启aof和rdb,aof的优先级更高,会优先使用aof进行数据恢复)
手动删除redis容器,查看自动重建的redis中是否存在之前创建的数据
kubectl delete pod deploy-devops-redis-6c8874b84d-zwlvw -n magedu
查看新建的pod,在172.31.7.111上(第一次创建在172.31.7.113上),已经重建
进入容器,查看数据仍然存在,说明aof备份已生效
9.4.4 K8S部署redis集群
redis集群有主从节点,一般情况下会设置三主三从。
每个主节点对应一个从节点。当主节点宕机后,从节点会代替主节点进行工作。
另外,每个节点的数据不一致,因此每个节点都需要配置pv/pvc。
架构图:
Redis 集群的好处:
数据分片:将数据自动切分(split)到多个节点的能力。
当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。
什么叫数据分片:
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个,集群中的每个节点负责处理一部分哈希槽。
假设一个集群有三个节点, 其中:
节点 A 负责处理 0 号至 5500 号哈希槽。
节点 B 负责处理 5501 号至 11000 号哈希槽。
节点 C 负责处理 11001 号至 16384 号哈希槽。
这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。
假设,向集群写入数据,设置一个key,叫my_name:
set my_name zhangsan
如果发现该key的槽位为0-5500,那么这个key就被分配到了节点A上,当我连接(A,B,C)的任意一个节点想获取my_name这个key,都会将请求转到节点A上,其他节点同理。
添加或删除节点不影响集群服务
如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 即可。
如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 即可
因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线。
9.4.4.1 创建pv
1、在nfs存储(172.31.7.109)上创建挂载目录
mkdir -p /data/k8sdata/magedu/redis{0,1,2,3,4,5}
注意:由于nfs配置文件中/etc/exports中/data/k8sdata/magedu已经做过配置,这里可以直接使用,如果使用的挂载路径没有使用过,这里需要在/etc/exprots中进行配置
2、在master1节点创建存放文件目录
mkdir -p /root/k8s-data/yaml/magedu/redis-cluster/pv
cd /root/k8s-data/yaml/magedu/redis-cluster/pv
3、编写yaml文件
(1)手动创建pv(一共6个节点,因此创建6个pv)
vim redis-persistentvolume.yaml
redis-cluster-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-cluster-pv0
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/redis0
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-cluster-pv1
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/redis1
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-cluster-pv2
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/redis2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-cluster-pv3
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/redis3
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-cluster-pv4
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/redis4
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-cluster-pv5
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/redis5
创建pv
kubectl apply -f redis-cluster-pv.yaml
查看pv
注意:这里只创建了pv,pvc的创建在k8s集群部署redis集群时通过yaml文件指定。这是因为有6个节点,手动创建pvc比较麻烦,通过yaml文件的方式创建pvc比较方便
9.4.4.2 k8s部署redis
1、创建存放yaml文件的目录
mkdir -p /root/k8s-data/yaml/magedu/redis-cluster
cd /root/k8s-data/yaml/magedu/redis-cluster
2、准备工作
(1)准备redis集群配置文件,以configmap形式挂载到redis容器中(也可以在构建镜像时把配置写入镜像中)
vim redis.conf
appendonly yes #开启aof
cluster-enabled yes #开启集群,必须开启,否则无法创建集群
cluster-config-file /var/lib/redis/nodes.conf #集群配置文件,自动生成
cluster-node-timeout 5000 #集群初始化超时时间,超出该时间就会报错
dir /var/lib/redis #数据目录
port 6379 #端口
(2)基于配置文件创建configmap
kubectl create configmap redis-conf --from-file=redis.conf -n magedu
查看configmap
注意:configmap一定要提前创建,否则redis集群无法加载配置文件,集群部署会失败
3、编写yaml文件
vim redis.yaml
redis.yaml
apiVersion: v1
kind: Service #创建集群内部访问的service
metadata:
name: redis
namespace: magedu
labels:
app: redis
spec:
selector:
app: redis
appCluster: redis-cluster
ports:
- name: redis
port: 6379
clusterIP: None #无头服务,service会被直接解析为pod地址
---
apiVersion: v1
kind: Service
metadata:
name: redis-access
namespace: magedu
labels:
app: redis
spec:
selector:
app: redis
appCluster: redis-cluster
ports:
- name: redis-access
protocol: TCP
port: 6379
targetPort: 6379
---
apiVersion: apps/v1
kind: StatefulSet #使用statefulset类型控制器,指定redis0/redis1/redis2为主节点,如果不指定,则可以使用deployment类型控制器
metadata:
name: redis
namespace: magedu
spec:
serviceName: redis
replicas: 6
selector:
matchLabels:
app: redis
appCluster: redis-cluster
template:
metadata:
labels:
app: redis
appCluster: redis-cluster
spec:
terminationGracePeriodSeconds: 20 #指定容器关闭前的延迟时间
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution: #指定容器亲和
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
topologyKey: kubernetes.io/hostname
containers:
- name: redis
image: redis:4.0.14 #使用官方镜像
imagePullPolicy: Always #设置镜像拉取策略,设置为always是为了后续实验,一般情况下会设置为IfNotPresent
command: #由于使用官方镜像,要通过命令启动redis,如果使用自构建的镜像,该命令可以不写
- "redis-server"
args: #传参,关闭安全模式(如果开启,要设置redis密码)
- "/etc/redis/redis.conf"
- "--protected-mode"
- "no"
resources:
requests:
cpu: "500m"
memory: "500Mi"
ports:
- containerPort: 6379
name: redis
protocol: TCP
- containerPort: 16379
name: cluster
protocol: TCP
volumeMounts:
- name: conf
mountPath: /etc/redis #挂载configmap作为redis集群配置文件
- name: data
mountPath: /var/lib/redis #挂载数据目录
volumes:
- name: conf
configMap:
name: redis-conf
items:
- key: redis.conf
path: redis.conf
volumeClaimTemplates: #指定pvc模板,如果集群内没有pvc,会自动创建pvc,无需手动创建,每创建一个pod,就将pvc挂载到pod上。添加该配置时,集群内要提前创建好pv。
- metadata:
name: data
namespace: magedu
spec:
accessModes: [ "ReadWriteOnce" ] #设置权限,每个pvc以读写权限被单个pod挂载
resources:
requests:
storage: 5Gi
4、创建pod(由于使用statefulset控制器创建pod,pod会被顺序创建出来)
kubectl apply -f redis.yaml
5、查看redis
6、查看pvc
pvc名称格式:<volumeClaimTemplates-metadata-name>-<statefulset-name>-<顺序编号>
注意:此时只是将6个单机的redis创建出来,还需要对redis进行初始化。
9.4.4.3 redis集群初始化
初始化只需要初始化一次,redis 4及之前的版本需要使用redis-tribe工具进行初始化,redis 5开始使用redis-cli。
1、在k8s集群内部单独创建一个ubuntu容器进行集群初始化操作
kubectl run -it ubuntu1804 --image=ubuntu:18.04 --restart=Never -n magedu bash
root@ubuntu1804:/# apt update #更新仓库
root@ubuntu1804:/# apt install python2.7 python-pip redis-tools dnsutils iputils-ping net-tools #安装需要的软件和工具
root@ubuntu1804:/# pip install --upgrade pip #自动安装的pip版本较低,更新pip版本
root@ubuntu1804:/# pip install redis-trib==0.5.1 #安装redis集群初始化工具redis-trib
验证:可以执行redis-trib命令
2、创建集群
首先将redis0,redis1,redis2加入集群作为主节点。
由于创建redis的时候,redis的service使用的是无头服务类型,redis的servicename会被解析为redis的pod地址,因此在创建集群时,可以直接指定redis的podIP地址(如果使用虚拟机创建redis集群,则可以直接写虚拟机地址)
通过手动添加ip地址的方式有一个缺点:如果redis容器被重建,容器ip地址会发生变化,因此如果redis容器地址发生变化后,再次添加节点时不能复用以前的地址,需要注意容器ip地址的变化。
因此可以使用dig命令解析servicename来获取redis容器ip地址
即:dig +short redis-0.redis.magedu.svc.magedu.local
查看podIP
创建redis集群:
在ubuntu容器中执行命令
root@ubuntu1804:/# redis-trib.py create \
10.200.36.66:6379 \
10.200.107.223:6379 \
10.200.169.180:6379
为每个redis主节点添加从节点(redis0的slave节点是redis3,redis1的slave节点是redis4,redis2的slave节点是redis5)
(1)将redis-3加入redis-0:
root@ubuntu1804:/# redis-trib.py replicate \
--master-addr 10.200.36.66:6379 \
--slave-addr 10.200.36.79:6379
(2)将redis-4加入redis-1:
root@ubuntu1804:/# redis-trib.py replicate \
--master-addr 10.200.107.223:6379 \
--slave-addr 10.200.107.251:6379
(3)将redis-5加入redis-2:
root@ubuntu1804:/# redis-trib.py replicate \
--master-addr 10.200.169.180:6379 \
--slave-addr 10.200.169.181:6379
3、验证:
(1)通过redis客户端进入集群查看集群状态以及集群节点信息
在master1节点执行命令
kubectl exec -it redis-0 bash -n magedu
root@redis-0:/data# redis-cli #通过客户端命令进入redis集群
127.0.0.1:6379> CLUSTER INFO #查看集群信息
127.0.0.1:6379> CLUSTER NODES #查看集群节点信息
(2)验证:数据的同步
在redis0容器内进入redis集群,随意写入一个数据
kubectl exec -it redis-0 bash -n magedu
root@redis-0:/data# redis-cli
127.0.0.1:6379> set test1 20220518
4、如果写入时提示error,说明没有写入到本机
此时,我们只需改动key值,从key1改为key2,继续测试,返回ok,说明已经写入本机
127.0.0.1:6379> set test2 20220518
5、获取数据
此时进入到redis0的从节点redis3查看key是否存在
但是无法查看key2的值(redis集群中读写均在主节点进行,从节点无法进行读写)
6、验证:
宕机一个master节点,slave是否会接管成为master
(1)删除redis-0容器
kubectl delete pod redis-0 -n magedu
(2)查看redis-0被重建
(3)进入redis-3,查看集群节点角色,redis-3已经变为master角色,说明主从切换成功,从节点已经切换为master
kubectl exec -it redis-3 bash -n magedu
root@redis-3:/data# redis-cli
127.0.0.1:6379> info
注意:redis集群初始化步骤也可以参考以下文档,文档链接(百度网盘)如下:
链接:https://pan.baidu.com/s/1Rhau8z4h_XpgDQHckW1y7Q
提取码:3o41
9.5 案例五:kubernetes基于StatefulSet运行MySQL一主多从
mysql主从基于StatefulSet控制器实现:
https://kubernetes.io/zh/docs/tasks/run-application/run-replicated-stateful-application/
Pod调度运行时,如果应用不需要任何稳定的标示、有序的部署、删除和扩展,则应该使用一组无状态副本的控制器来部署应用,例如 Deployment 或 ReplicaSet更适合无状态服务需求,而StatefulSet适合管理所有有状态的服务,比如MySQL、MongoDB集群等。
mysql一主多从架构图:
StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。
在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
StatefulSet 特点:
给每个pod分配固定且唯一的网络标识符
给每个pod分配固定且持久化的外部存储
对pod进行有序的部署和扩展
对pod进有序的删除和终止
对pod进有序的自动滚动更新
statefulset组成部分:
Headless Service:用来定义Pod网络标识( DNS domain),指的是短的serfvice(丢失了domainname)。
StatefulSet:定义具体应用,有多少个Pod副本,并为每个Pod定义了一个域名。
volumeClaimTemplates: 存储卷申请模板,创建PVC,指定pvc名称大小,将自动创建pvc,且pvc必须由存储类供应。
配置statefulset控制器,就会涉及到无头服务(headerless service)
如果使用无头服务,则service没有ip,解析service名称时会直接返回容器的ip地址,在mysql主从中,解析service会随机返回主从节点的ip地址,无法进行控制。
如果想要实现mysql读写分离,可以指定mysql主从中master节点名,使master来接收写操作。master名称是固定唯一不变的,可以通过指定名称来承载写操作,而且slave节点可以通过master节点的名称同步数据。
然后为slave专门创建一个service,用来将读请求转发给slave。
这样,就能实现读写分离。
这里有三个名称需要注意:
master pod名称固定不变,一般为<mysql-0.mysql.>
无头服务service为mysql,解析该名称,会随机返回主从节点的ip,无法控制
只读请求service为mysql-read,用来接收读请求,然后转发给slave
逻辑架构图:
注意:业务容器和高运算容器(如elk、hadoop等消耗资源较高的服务)进行独立部署,如果两种类型的容器混合部署(部署在同一个物理机),高运算容器一旦占用资源过多,会影响同一台物理机上的其他业务容器,对业务产生影响。
9.5.1 准备镜像
实现mysql主从,要使用两个镜像:使用mysql镜像拉起服务,使用xtrabackup镜像实现数据同步
1、从互联网获取镜像,并上传到本地镜像仓库
(1)获取xtrabackup镜像
docker pull registry.cn-hangzhou.aliyuncs.com/hxpdocker/xtrabackup:1.0
docker tag registry.cn-hangzhou.aliyuncs.com/hxpdocker/xtrabackup:1.0 harbor.magedu.local/magedu/xtrabackup:1.0
docker push harbor.magedu.local/magedu/xtrabackup:1.0
(2)获取mysql镜像
docker pull mysql:5.7
docker tag mysql:5.7 harbor.magedu.local/magedu/mysql:5.7.36
docker push harbor.magedu.local/magedu/mysql:5.7.36
9.5.2 创建pv
1、在nfs存储(172.31.7.109)上创建挂载目录(一共创建6个目录,以作备用)
mkdir -p /data/k8sdata/magedu/mysql-datadir-{1,2,3,4,5,6}
注意:由于nfs配置文件中/etc/exports中/data/k8sdata/magedu已经做过配置,这里可以直接使用,如果使用的挂载路径没有使用过,这里需要在/etc/exprots中进行配置
2、在master1节点创建存放文件目录
mkdir -p /root/k8s-data/yaml/magedu/mysql/pv
cd /root/k8s-data/yaml/magedu/mysql/pv
3、编写yaml文件
(1)创建pv
vim mysql-persistentvolume.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-datadir-1
namespace: magedu
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/k8sdata/magedu/mysql-datadir-1
server: 172.31.7.109
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-datadir-2
namespace: magedu
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/k8sdata/magedu/mysql-datadir-2
server: 172.31.7.109
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-datadir-3
namespace: magedu
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/k8sdata/magedu/mysql-datadir-3
server: 172.31.7.109
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-datadir-4
namespace: magedu
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/k8sdata/magedu/mysql-datadir-4
server: 172.31.7.109
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-datadir-5
namespace: magedu
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/k8sdata/magedu/mysql-datadir-5
server: 172.31.7.109
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-datadir-6
namespace: magedu
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/k8sdata/magedu/mysql-datadir-6
server: 172.31.7.109
创建pv
kubectl apply -f mysql-persistentvolume.yaml
查看pv
注意:这里只创建了pv,pvc的创建在k8s集群部署redis集群时通过yaml文件指定。这是因为有6个节点,手动创建pvc比较麻烦,通过yaml文件的方式创建pvc比较方便
9.5.3 k8s部署mysql主从
1、创建存放yaml文件的目录
mkdir -p /root/k8s-data/yaml/magedu/mysql
cd /root/k8s-data/yaml/magedu/mysql
2、准备mysql配置文件,以configmap形式挂载作为mysql主从的配置文件
vim mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
namespace: magedu
labels:
app: mysql
data:
master.cnf: |
# Apply this config only on the master. #master的配置
[mysqld]
log-bin
log_bin_trust_function_creators=1
lower_case_table_names=1
slave.cnf: |
# Apply this config only on slaves. #slave的配置
[mysqld]
super-read-only
log_bin_trust_function_creators=1
创建configmap
kubectl apply -f mysql-configmap.yaml
3、准备service yaml文件
这里有三个名称需要注意:
master pod名称固定不变,一般为<mysql-0.mysql.>
配置无头服务service为mysql,解析该名称,会随机返回主从节点的ip,无法控制
配置只读请求service为mysql-read,用来接收读请求,然后转发给slave
编写yaml文件
vim mysql-services.yaml
# Headless service for stable DNS entries of StatefulSet members.
apiVersion: v1
kind: Service
metadata:
namespace: magedu
name: mysql
labels:
app: mysql
spec:
ports:
- name: mysql
port: 3306
clusterIP: None #配置clusterIP为none,即headerless service(无头服务)
selector:
app: mysql
---
# Client service for connecting to any MySQL instance for reads.
# For writes, you must instead connect to the master: mysql-0.mysql.
apiVersion: v1
kind: Service
metadata:
name: mysql-read #名称
namespace: magedu
labels:
app: mysql
spec:
ports:
- name: mysql
port: 3306
selector:
app: mysql
注意:这里指定了两个类型的service:
创建service
kubectl apply -f mysql-services.yaml
4、编辑mysql yaml文件
vim mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: magedu
spec:
selector:
matchLabels:
app: mysql
serviceName: mysql
replicas: 3 #创建三副本,即一主两从
template:
metadata:
labels:
app: mysql
spec:
initContainers: #第一个初始化容器,初始化mysql运行环境
- name: init-mysql
image: harbor.magedu.local/magedu/mysql:5.7.36
command: #通过命令判断容器角色,并把对应配置文件复制过去
- bash
- "-c"
- |
set -ex
# Generate mysql server-id from pod ordinal index. #生成mysql server-id
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
echo [mysqld] > /mnt/conf.d/server-id.cnf #把配置echo到配置文件中,该文件以configmap形式挂载到容器内。
# Add an offset to avoid reserved server-id=0 value. #添加server-id到文件中(mysql主从各节点server-id不能一样)
echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
# Copy appropriate conf.d files from config-map to emptyDir. #根据server-id判断主从,如果server-id为0,就把congfigmap中的master.cnf配置复制到配置文件子目录中,否则就把slave.cnf配置复制到配置文件子目录中。
if [[ $ordinal -eq 0 ]]; then
cp /mnt/config-map/master.cnf /mnt/conf.d/
else
cp /mnt/config-map/slave.cnf /mnt/conf.d/
fi
volumeMounts: #配置emptydir,用来临时中转mysql配置文件
- name: conf #用来接收中转过来的mysql配置文件
mountPath: /mnt/conf.d
- name: config-map #用来存放configmap中的配置文件
mountPath: /mnt/config-map
- name: clone-mysql #第二个初始化容器,复制mysql数据到从节点
image: harbor.magedu.local/magedu/xtrabackup:1.0
command:
- bash
- "-c"
- |
set -ex
# Skip the clone if data already exists. #判断数据目录是否存在
[[ -d /var/lib/mysql/mysql ]] && exit 0
# Skip the clone on master (ordinal index 0). #判断hostname最后一位是否为0,如果为0,角色是master,正常退出,如果非0则是slave,要把数据从master复制到slave
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
[[ $ordinal -eq 0 ]] && exit 0
# Clone data from previous peer.
ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
# Prepare the backup.
xtrabackup --prepare --target-dir=/var/lib/mysql
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
containers: #业务容器
- name: mysql
image: harbor.magedu.local/magedu/mysql:5.7.36
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD #mysql需要设置密码,通过传参,配置允许空密码
value: "1"
ports:
- name: mysql
containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
resources:
requests:
cpu: 500m
memory: 1Gi
livenessProbe: #存活探针
exec:
command: ["mysqladmin", "ping"]
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe: #就绪探针
exec:
# Check we can execute queries over TCP (skip-networking is off).
command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"]
initialDelaySeconds: 5
periodSeconds: 2
timeoutSeconds: 1
- name: xtrabackup #xtrabackup容器,实现mysql主从的数据同步
image: harbor.magedu.local/magedu/xtrabackup:1.0
ports:
- name: xtrabackup
containerPort: 3307
command:
- bash
- "-c"
- |
set -ex
cd /var/lib/mysql
# Determine binlog position of cloned data, if any. #生成change_master命令
if [[ -f xtrabackup_slave_info ]]; then
# XtraBackup already generated a partial "CHANGE MASTER TO" query
# because we're cloning from an existing slave.
mv xtrabackup_slave_info change_master_to.sql.in
# Ignore xtrabackup_binlog_info in this case (it's useless).
rm -f xtrabackup_binlog_info
elif [[ -f xtrabackup_binlog_info ]]; then
# We're cloning directly from master. Parse binlog position.
[[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
rm xtrabackup_binlog_info
echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
fi
# Check if we need to complete a clone by starting replication.
if [[ -f change_master_to.sql.in ]]; then
echo "Waiting for mysqld to be ready (accepting connections)"
until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 1; done
echo "Initializing replication from clone position"
# In case of container restart, attempt this at-most-once.
mv change_master_to.sql.in change_master_to.sql.orig
mysql -h 127.0.0.1 <<EOF
$(<change_master_to.sql.orig), #执行命令把数据库指向主mysql-0.mysql
MASTER_HOST='mysql-0.mysql',
MASTER_USER='root',
MASTER_PASSWORD='',
MASTER_CONNECT_RETRY=10;
START SLAVE;
EOF
fi
# Start a server to send backups when requested by peers.
exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
"xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root"
volumeMounts:
- name: data #指定mysql数据挂载目录,并挂载pvc(通过指定pvc名称data来挂载)
mountPath: /var/lib/mysql
subPath: mysql
- name: conf #指定mysql配置文件挂载目录,以configmap形式挂载到容器内
mountPath: /etc/mysql/conf.d
resources:
requests:
cpu: 100m
memory: 100Mi
volumes:
- name: conf
emptyDir: {}
- name: config-map
configMap:
name: mysql
volumeClaimTemplates: #配置pvc,这里配置pvc以后,无需再手动配置
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
5、创建mysql主从(由于使用statefulset类型控制器,容器会按顺序进行创建)
kubectl apply -f mysql-statefulset.yaml
6、查看容器
注意:READY为2,该pod中存在两个容器,mysql容器提供服务,xtrabackup容器进行主从数据同步
7、验证1:查看主从同步状态
(1)进入slave节点查看主从同步状态
kubectl exec -it mysql-1 bash -n magedu
root@mysql-1:/# mysql #设置空密码,登录无需密码
mysql> show slave status\G
两个同步线程都为Yes,说明主从同步正常
(2)验证:
在主库创建数据库,能否同步到从库
kubectl exec -it mysql-0 bash -n magedu
root@mysql-0:/# mysql
在主库创建数据库,查看当前数据库状态
在从库进行查询,数据库同步成功。
8、验证:对slave进行扩缩容
(1)直接更改yaml文件的副本数,然后重新apply加载即可
将副本数设置为5,即slave扩容到4个(一主四从):
注意:扩容顺序为从前向后扩容
(2)查看扩容出来的slave主从同步状态以及数据是否存在
主从同步状态正常
刚才写入的数据,在新扩容的节点上也存在
(3)将副本数设置为2,即slave缩容到1个(一主一从):
注意:缩容顺序为从后向前缩容
另外,如果mysql配置了读写分离,可以把写操作指向mysql-0(master节点名称),写操作指向mysql-read(mysql-read是通过service yaml文件拉起的service,会将读请求转发给slave)
9.6 案例六:kubernetes运行Jenkins
9.6.1 构建镜像
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/jenkins
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/magedu/Jenkins
(1)准备jenkins war包(通过清华大学镜像源下载)
wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.319/jenkins.war --no-check-certificate
mv jenkins.war jenkins-2.319.2.war
(2)准备运行脚本脚本(使用java命令运行jenkins,指定jenkins数据目录为/apps/jenkins/jenkins-data,后续在yaml文件中会用到)
vim run_jenkins.sh
#!/bin/bash
cd /apps/jenkins && java -server -Xms1024m -Xmx1024m -Xss512k -jar jenkins.war --webroot=/apps/jenkins/jenkins-data --httpPort=8080
chmod a+x run_jenkins.sh #为脚本添加可执行权限,否则在容器内无法运行该脚本
3、编写dockerfile文件
由于jenkins需要java环境,因此需要java基础镜像,父镜像使用9.1.2.2.1章节构建出来的jdk基础镜像
vim Dockerfile
#Jenkins Version 2.190.1
FROM harbor.magedu.local/pub-images/jdk-base:v8.212
MAINTAINER zhangshijie zhangshijie@magedu.net
ADD jenkins-2.319.2.war /apps/jenkins/jenkins.war
ADD run_jenkins.sh /usr/bin/
EXPOSE 8080
CMD ["/usr/bin/run_jenkins.sh"]
4、编写构建镜像的脚本
vim build-command.sh
#!/bin/bash
docker build -t harbor.magedu.local/magedu/jenkins:v2.319.2 .
echo "镜像制作完成,即将上传至Harbor服务器"
sleep 1
docker push harbor.magedu.local/magedu/jenkins:v2.319.2
echo "镜像上传完成"
5、运行脚本,构建镜像
bash build-command.sh
6、验证:
手动拉起容器,查看镜像是否可用
docker run -it --rm -p 8080:8080 harbor.magedu.local/magedu/jenkins:v2.319.2
jenkins的配置文件目录为/root/.jenkins(拉起jenkins服务用户家目录下的.jenkins目录)
jenkins的数据目录为/apps/jenkins/jenkins-data/
当在k8s集群部署jenkins时,需要把jenkins的配置文件目录和数据目录挂载到存储上(数据持久化),这样即使jenkins出现问题,数据也不会丢失
9.6.2 创建pv/pvc
创建两个pv和pvc,分别用来存储jenkins的配置文件和数据文件
1、在nfs存储(172.31.7.109)上创建挂载目录
mkdir -p /data/k8sdata/magedu/jenkins-data
mkdir -p /data/k8sdata/magedu/jenkins-root-data
注意:由于nfs配置文件中/etc/exports中/data/k8sdata/magedu已经做过配置,这里可以直接使用,如果使用的挂载路径没有使用过,这里需要在/etc/exprots中进行配置
2、在master1节点创建存放文件目录
mkdir -p /root/k8s-data/yaml/magedu/jenkins/pv
cd /root/k8s-data/yaml/magedu/jenkins/pv
3、编写yaml文件
(1)创建pv
vim jenkins-persistentvolume.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins-datadir-pv
namespace: magedu
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/jenkins-data
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: jenkins-root-datadir-pv
namespace: magedu
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
nfs:
server: 172.31.7.109
path: /data/k8sdata/magedu/jenkins-root-data
创建pv
kubectl apply -f redis-persistentvolume.yaml
查看pv
(2)创建pvc
vim jenkins-persistentvolumeclaim.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-datadir-pvc
namespace: magedu
spec:
volumeName: jenkins-datadir-pv
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 80Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: jenkins-root-data-pvc
namespace: magedu
spec:
volumeName: jenkins-root-datadir-pv
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 80Gi
创建pvc
kubectl apply -f redis-persistentvolumeclaim.yaml
查看pvc
9.6.3 K8S部署jenkins
1、创建存放yaml文件的目录
mkdir -p /root/k8s-data/yaml/magedu/zookeeper
2、编写 yaml文件
vim jenkins.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-jenkins
name: magedu-jenkins-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-jenkins
template:
metadata:
labels:
app: magedu-jenkins
spec:
containers:
- name: magedu-jenkins-container
image: harbor.magedu.local/magedu/jenkins:v2.319.2
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always #设置镜像拉取策略,为了便于后续演示,设置为always,一般情况下会设置为IfNotPresent
ports:
- containerPort: 8080
protocol: TCP
name: http
volumeMounts:
- mountPath: "/apps/jenkins/jenkins-data/" #指定挂载jenkins数据文件的路径
name: jenkins-datadir-magedu
- mountPath: "/root/.jenkins" #指定挂载jenkins配置文件的路径
name: jenkins-root-datadir
volumes:
- name: jenkins-datadir-magedu
persistentVolumeClaim:
claimName: jenkins-datadir-pvc
- name: jenkins-root-datadir
persistentVolumeClaim:
claimName: jenkins-root-data-pvc
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-jenkins
name: magedu-jenkins-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
nodePort: 38080 #暴露端口,便于外部服务访问
selector:
app: magedu-jenkins
3、创建容器
kubectl apply -f jenkins.yaml
4、查看jenkins容器
通过浏览器访问 172.31.7.111:38080
进入容器,查看下图红框内文件内容,输入才可以进入jenkins web页面
5、jenkins安装插件
(1)新手入门可以根据推荐进行插件安装,有使用经验的可以根据需求安装插件
注意:这里的插件会保存到/root/.jenkins/plugins目录下,保存在存储上,jenkins容器重启,插件不会丢失。
另外,如果jenkins不能联网,可以在一个联网的jenkins上下载完之后,把插件复制到相同目录下,然后重新构建jenkins,jenkins会自动加载插件(jenkins版本要相同)
插件安装:绿色表示安装成功,红色表示安装失败
(2)创建用户
(3)继续下一步
(4)开始使用
9.7 案例七:单Pod多容器实现LNMP并使用MySQL作为SQL服务器
在K8S集群部署wordpress,以nginx+php实现,静态请求nginx进行处理,动态请求转发给php,因此需要构建nginx镜像和php进行
架构图:
9.7.1 构建镜像
9.7.1.1 构建nginx镜像
第1步:构建nginx基础镜像(只安装nginx,没有nginx配置)
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/pub-images/nginx-base-wordpress
2、准备nginx Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/pub-images/nginx-base-wordpress
下载nginx安装包
wget http://nginx.org/download/nginx-1.20.2.tar.gz
3、编写Dokcefile文件(基于9.1.2.1章节构建的centos-base镜像,安装nginx)
vim Dockerfile
#Nginx Base Image
FROM harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009
MAINTAINER 957464230@qq.com
RUN yum install -y vim wget tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
ADD nginx-1.20.2.tar.gz /usr/local/src/
RUN cd /usr/local/src/nginx-1.20.2 && ./configure --prefix=/apps/nginx && make && make install && ln -sv /apps/nginx/sbin/nginx /usr/sbin/nginx &&rm -rf /usr/local/src/nginx-1.20.2.tar.gz
4、编写构建镜像的脚本
vim build-command.sh
#!/bin/bash
docker build -t harbor.magedu.local/pub-images/nginx-base-wordpress:v1.20.2 .
sleep 1
docker push harbor.magedu.local/pub-images/nginx-base-wordpress:v1.20.2
5、运行脚本,构建镜像
bash build-command.sh
第2步:构建nginx镜像(将nginx配置加入nginx镜像)
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/wordpress/nginx
2、准备nginx Dockerfile需要的文件
(1)准备nginx配置文件
cd /root/k8s-data/dockerfile/web/magedu/wordpress/nginx
vim nginx.conf
nginx.conf
user nginx nginx;
worker_processes auto;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
#daemon off;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
client_max_body_size 10M;
client_body_buffer_size 16k;
client_body_temp_path /apps/nginx/tmp 1 2 2;
gzip on;
server {
listen 80;
server_name blogs.magedu.net;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /home/nginx/wordpress;
index index.php index.html index.htm;
#if ($http_user_agent ~ "ApacheBench|WebBench|TurnitinBot|Sogou web spider|Grid Service") {
# proxy_pass http://www.baidu.com;
# #return 403;
#}
}
location ~ \.php$ { #配置php转发
root /home/nginx/wordpress;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
#fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
(2)准备nginx默认页面
vim index.html
nginx web1
(3)准备nginx运行脚本
vim run_nginx.sh
#!/bin/bash
#echo "nameserver 10.20.254.254" > /etc/resolv.conf
#chown nginx.nginx /home/nginx/wordpress/ -R
/apps/nginx/sbin/nginx
tail -f /etc/hosts
chmod a+x run_nginx.sh
3、编写nginx dockerfile文件(注意nginx用户和php用户要保持一致,uid和gid也要保持一致)
vim Dockerfile
FROM harbor.magedu.local/pub-images/nginx-base-wordpress:v1.20.2
ADD nginx.conf /apps/nginx/conf/nginx.conf
ADD run_nginx.sh /apps/nginx/sbin/run_nginx.sh
RUN mkdir -pv /home/nginx/wordpress
RUN useradd nginx -u 2088 && chown nginx.nginx /home/nginx/wordpress/ -R
EXPOSE 80 443
CMD ["/apps/nginx/sbin/run_nginx.sh"]
4、编写构建镜像脚本
vim build-command.sh
build-command.sh
#!/bin/bash
TAG=$1
docker build -t harbor.magedu.local/magedu/wordpress-nginx:${TAG} .
echo "镜像制作完成,即将上传至Harbor服务器"
sleep 1
docker push harbor.magedu.local/magedu/wordpress-nginx:${TAG}
echo "镜像上传完成"
5、运行脚本,构建镜像
bash build-command.sh v1.20.2
验证:
是否可以根据镜像拉起容器
docker run -it --rm harbor.magedu.local/magedu/wordpress-nginx:v1.20.2
第3步:构建php镜像
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/wordpress/php
2、准备php Dockerfile需要的文件
(1)准备php配置文件(更改php账号为nginx,要和nginx保持一致)
vim www.conf
[www]
user = nginx
group = nginx
listen = 0.0.0.0:9000
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /opt/remi/php56/root/var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /opt/remi/php56/root/var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /opt/remi/php56/root/var/lib/php/session
php_value[soap.wsdl_cache_dir] = /opt/remi/php56/root/var/lib/php/wsdlcache
注意:以上内容为简化版,详细配置文件可参考以下链接(百度网盘):
链接:https://pan.baidu.com/s/1N5RWLWhln-4hxisN5DVW1Q
提取码:ugzf
(2)准备php运行脚本
vim run_php.sh
#!/bin/bash
/opt/remi/php56/root/usr/sbin/php-fpm
tail -f /etc/hosts
3、编写php dockerfile文件(yum安装php仓库和php56,替换php配置文件www.conf,添加php账号,要和nginx账号(包括uid和gid)保持一致)
vim Dockerfile
#PHP Base Image
FROM harbor.magedu.local/baseimages/magedu-centos-base:7.9.2009
MAINTAINER zhangshijie@magedu.net
RUN yum install -y https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm && yum install php56-php-fpm php56-php-mysql -y && useradd nginx -u 2088
ADD www.conf /opt/remi/php56/root/etc/php-fpm.d/www.conf
#RUN useradd nginx -u 2019
ADD run_php.sh /usr/local/bin/run_php.sh
EXPOSE 9000
CMD ["/usr/local/bin/run_php.sh"]
4、编写构建镜像脚本
vim build-command.sh
#!/bin/bash
TAG=$1
docker build -t harbor.magedu.local/magedu/wordpress-php-5.6:${TAG} .
echo "镜像制作完成,即将上传至Harbor服务器"
sleep 1
docker push harbor.magedu.local/magedu/wordpress-php-5.6:${TAG}
echo "镜像上传完成"
5、运行脚本,构建镜像
bash build-command.sh v1
9.7.2 K8S集群部署wordpress
1、在nfs存储(172.31.7.109)上创建挂载目录
mkdir -p /data/k8sdata/magedu/wordpress
注意:由于nfs配置文件中/etc/exports中/data/k8sdata/magedu已经做过配置,这里可以直接使用,如果使用的挂载路径没有使用过,这里需要在/etc/exprots中进行配置
2、创建存放文件的目录
mkdir -p /root/k8s-data/yaml/magedu/wordpress
cd /root/k8s-data/yaml/magedu/wordpress
3、编写yaml文件
vim wordpress.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: wordpress-app
name: wordpress-app-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: wordpress-app
template:
metadata:
labels:
app: wordpress-app
spec:
containers:
- name: wordpress-app-nginx #创建nginx容器
image: harbor.magedu.local/magedu/wordpress-nginx:v1.20.2
#imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
- containerPort: 443
protocol: TCP
name: https
volumeMounts:
- name: wordpress
mountPath: /home/nginx/wordpress #指定挂载路径
readOnly: false
- name: wordpress-app-php #创建php容器
image: harbor.magedu.local/magedu/wordpress-php-5.6:v1
#image: harbor.magedu.net/magedu/php:5.6.40-fpm
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 9000
protocol: TCP
name: http
volumeMounts:
- name: wordpress
mountPath: /home/nginx/wordpress #指定挂载路径
readOnly: false
volumes:
- name: wordpress
nfs: #使用nfs存储作为存储卷
server: 172.31.7.109
path: /data/k8sdata/magedu/wordpress
---
kind: Service
apiVersion: v1
metadata:
labels:
app: wordpress-app
name: wordpress-app-spec
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
nodePort: 30031
- name: https
port: 443
protocol: TCP
targetPort: 443
nodePort: 30033 #暴露端口供外部访问
selector:
app: wordpress-app
创建容器
kubectl apply -f wordpress.yaml
查看pod(同一个pod下有两个容器,READY为2/2)
4、验证
在nfs存储172.31.7.109上挂载目录下存放php测试页
vim /data/k8sdata/magedu/wordpress/index.php
<?php
phpinfo();
?>
在浏览器访问验证:172.31.7.113:30031
页面可以正常展示,说明php服务正常
5、把wordpress放到共享存储目录/data/k8sdata/magedu/wordpress下
在172.31.7.109上执行以下命令:
cd /data/k8sdata/magedu/wordpress
(1)下载wordpress安装包
wget https://cn.wordpress.org/latest-zh_CN.tar.gz
(2)解压并将文件移动到当前目录
tar -xvf latest-zh_CN.tar.gz && mv wordpress/* ./ && mv wordpress/ latest-zh_CN.tar.gz /tmp/
6、设置负载均衡器,通过负载均衡器的VIP访问wordpress
在负载均衡器172.31.7.109上更改haproxy配置
vim /etc/haproxy/haproxy.cfg #在配置文件最下面加上以下配置
listen magedu-linux66-nginx-80
bind 172.31.7.189:80
mode tcp
server node1 172.31.7.111:30031 check inter 3s fall 3 rise 1
server node2 172.31.7.112:30031 check inter 3s fall 3 rise 1
server node3 172.31.7.113:30031 check inter 3s fall 3 rise 1
注意172.31.7.189为keepalived配置的VIP地址
重启服务,使配置生效
systemctl restart haproxy
在访问网站的终端上配置本地hosts,把VIP和域名绑定,这里把172.31.7.189和www.mysite.com这个域名进行绑定
7、wordpress初始化
(1)通过访问域名,访问wordpress
在浏览器输入:www.mysite.com
需要进行初始化,但是由于wordpress需要连接数据库,因此需要创建wordpress数据库
由于nginx和php使用的是nginx用户启动,因此要把wordpress的文件权限更改为nginx属主和属组,否则将无法写入数据。
但是由于nfs存储上没有nginx用户,可以把wordpress的文件权限指定为和nginx一样的uid和gid
在nfs存储172.31.7.109上
cd /data/k8sdata/magedu/wordpress
chown -R 2088:2088 /data/k8sdata/magedu/wordpress
(2)创建数据库(使用之前创建的mysql数据库),并进行授权(授权可以访问wordpress数据库的用户名和密码)
kubectl exec -it mysql-0 bash -n magedu
root@mysql-0:/# mysql
mysql> create database wordpress;
mysql> GRANT ALL PRIVILEGES ON wordpress.* TO "wordpress"@"%" IDENTIFIED BY "wordpress123"; #授权,wordpress用户以wordpress123密码访问wordpress数据库
mysql> flush privileges;
(3)web页面进行初始化
注意:数据库主机可以写mysql-0的名称(建议写全称)或者mysql-0的ip
如何查看数据mysql-0的全称:
进入mysql-0容器
cat /etc/hosts
继续进行下一步
注意:这里的密码是进入wordpress后台的密码,该密码在进入页面时会自动生成,也可以手动修改,该密码不要忘记,否则将无法登录wordpress后台
(4)登录wordpress后台
注意:这里的用户名和密码就是上一张截图中设置的用户名和密码
在后台可以编写博客文章
(5)访问网站前台:www.mysite.com
9.8 案例八:kubernetes基于Zookeeper案例实现微服务动态注册和发现案例
架构图:
服务发现流程:
1.服务端在配置文件中指定配置中心地址,当服务端运行时会将服务端地址上报给注册中心
2.客户端同时也配置注册中心地址,从注册中心获取服务端地址
3.客户端根据从注册中心获取的地址,直接访问服务端,这样就大大节省了访问流程,能提高效率。
4.一旦服务端某个节点宕机,注册中心会及时发现,并告知客户端,客户端将不会再请求已经宕机的服务节点。
这里的注册中心使用9.3章节部署好的zookeeper集群来实现。
9.8.1 构建镜像
9.8.1.1 构建生产者provider镜像
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/dubbo/provider
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/magedu/dubbo/provider
(1)准备provider配置文件
下载文件:dubbo-demo-provider-2.1.5-assembly.tar.gz
百度网盘链接:https://pan.baidu.com/s/1P0PrwyOPpYssFjALA5WIXg 提取码:5s6u
下载完成后上传到该目录下并解压
tar -xvf dubbo-demo-provider-2.1.5-assembly.tar.gz
cd /root/k8s-data/dockerfile/web/magedu/dubbo/provider/dubbo-demo-provider-2.1.5
该目录下有三个子目录,其中conf目录为配置文件目录
更改conf目录下的配置文件
cd conf/
vim dubbo.properties (文件需要指定zookeeper集群中zookeeper的地址和端口,这里写的是zookeeper service的全称)
dubbo.container=log4j,spring
dubbo.application.name=demo-provider
dubbo.application.owner=
dubbo.registry.address=zookeeper://zookeeper1.magedu.svc.magedu.local:2181 | zookeeper://zookeeper2.magedu.svc.magedu.local:2181 | zookeeper://zookeeper3.magedu.svc.magedu.local:2181
dubbo.monitor.protocol=registry
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.log4j.file=logs/dubbo-demo-provider.log
dubbo.log4j.level=WARN
如何获取zookeeper service全称:zookeeper servicename+namespace+svc+k8s集群域名后缀,即:zookeeper1.magedu.svc.magedu.local
(2)准备运行脚本(provider起来以后会将自己地址注册到注册中心)
cd /root/k8s-data/dockerfile/web/magedu/dubbo/provider
vim run_java.sh
#!/bin/bash
#echo "nameserver 223.6.6.6" > /etc/resolv.conf
#/usr/share/filebeat/bin/filebeat -c /etc/filebeat/filebeat.yml -path.home /usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs /var/log/filebeat &
su - nginx -c "/apps/dubbo/provider/bin/start.sh"
tail -f /etc/hosts
3、编写Dockerfile(添加nginx用户,添加配置文件,添加启动脚本,更改配置文件权限,为配置文件中bin目录下的脚本添加可执行权限,父镜像为9.1.2.2.1章节构建的jdk-base镜像)
vim Dockerfile
#Dubbo provider
FROM harbor.magedu.local/pub-images/jdk-base:v8.212
MAINTAINER "957464230@qq.com"
RUN yum install file nc -y
RUN useradd nginx -u 2088
RUN mkdir -p /apps/dubbo/provider
ADD dubbo-demo-provider-2.1.5/ /apps/dubbo/provider
ADD run_java.sh /apps/dubbo/provider/bin
RUN chown nginx.nginx /apps -R
RUN chmod a+x /apps/dubbo/provider/bin/*.sh
CMD ["/apps/dubbo/provider/bin/run_java.sh"]
4、编写构建镜像脚本
vim build-command.sh
#!/bin/bash
docker build -t harbor.magedu.local/magedu/dubbo-demo-provider:v1 .
sleep 3
docker push harbor.magedu.local/magedu/dubbo-demo-provider:v1
5、运行脚本,构建镜像
bash build-command.sh
6、手动拉起容器进行验证,可以正常
docker run -it --rm harbor.magedu.local/magedu/dubbo-demo-provider:v1
9.8.1.2 构建生产者consumer镜像
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/dubbo/consumer
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/magedu/dubbo/consumer
(1)准备provider配置文件
下载文件:dubbo-demo-consumer-2.1.5-assembly.tar.gz
百度网盘链接:https://pan.baidu.com/s/1P0PrwyOPpYssFjALA5WIXg 提取码:5s6u
下载完成后上传到该目录下并解压
tar -xvf dubbo-demo-consumer-2.1.5-assembly.tar.gz
cd /root/k8s-data/dockerfile/web/magedu/dubbo/consumer/dubbo-demo-consumer-2.1.5
该目录下有三个子目录,其中conf目录为配置文件目录
更改conf目录下的配置文件
cd conf/
vim dubbo.properties (文件需要指定zookeeper集群中zookeeper的地址和端口,这里写的是zookeeper service的全称)
dubbo.container=log4j,spring
dubbo.application.name=demo-consumer
dubbo.application.owner=
dubbo.registry.address=zookeeper://zookeeper1.magedu.svc.magedu.local:2181 | zookeeper://zookeeper2.magedu.svc.magedu.local:2181 | zookeeper://zookeeper3.magedu.svc.magedu.local:2181
dubbo.monitor.protocol=registry
dubbo.log4j.file=logs/dubbo-demo-consumer.log
dubbo.log4j.level=WARN
如何获取zookeeper service全称:zookeeper servicename+namespace+svc+k8s集群域名后缀,即:zookeeper1.magedu.svc.magedu.local
(2)准备运行脚本(consumer起来后会根据zookeeper地址向注册中心查询provider地址)
cd /root/k8s-data/dockerfile/web/magedu/dubbo/consumer
vim run_java.sh
#!/bin/bash
#/usr/share/filebeat/bin/filebeat -c /etc/filebeat/filebeat.yml -path.home /usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs /var/log/filebeat &
su - nginx -c "/apps/dubbo/consumer/bin/start.sh"
tail -f /etc/hosts
3、编写Dockerfile(添加nginx用户,添加配置文件,添加启动脚本,更改配置文件权限,为配置文件中bin目录下的脚本添加可执行权限,父镜像为9.1.2.2.1章节构建的jdk-base镜像)
vim Dockerfile
#Dubbo consumer
FROM harbor.magedu.local/pub-images/jdk-base:v8.212
MAINTAINER zhangshijie
RUN yum install file -y && useradd nginx -u 2088
RUN mkdir -p /apps/dubbo/consumer
ADD dubbo-demo-consumer-2.1.5 /apps/dubbo/consumer
ADD run_java.sh /apps/dubbo/consumer/bin
RUN chown nginx.nginx /apps -R
RUN chmod a+x /apps/dubbo/consumer/bin/*.sh
CMD ["/apps/dubbo/consumer/bin/run_java.sh"]
4、编写构建镜像脚本
vim build-command.sh
#!/bin/bash
docker build -t harbor.magedu.local/magedu/dubbo-demo-consumer:v1 .
sleep 3
docker push harbor.magedu.local/magedu/dubbo-demo-consumer:v1
5、运行脚本,构建镜像
bash build-command.sh
9.8.1.2 构建生产者dubboadmin镜像
该镜像用于创建管理dubbo服务的组件,基于tomcat运行
1、创建存放文件的目录
mkdir -p /root/k8s-data/dockerfile/web/magedu/dubbo/dubboadmin
2、准备Dockerfile需要的文件
cd /root/k8s-data/dockerfile/web/magedu/dubbo/dubboadmin
(1)准备war包,并修改配置
下载文件:dubboadmin.war
百度网盘链接:https://pan.baidu.com/s/1P0PrwyOPpYssFjALA5WIXg 提取码:5s6u
下载完成后上传到该目录下
一般情况下,该war包由研发提供,无需自己编写,这里为了便于实验,通过手动下载并更改配置
unzip -d dubboadmin.war
cd /root/k8s-data/dockerfile/web/magedu/dubbo/dubboadmin/dubboadmin/WEB-INF
vim dubbo.properties #指定zookeeper地址,这里指定为zookeeper1的service全称,并指定dubboadmin的登录密码为root。guest为普通用户
dubbo.registry.address=zookeeper://zookeeper1.magedu.svc.magedu.local:2181
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
将老的war移走,然后将更改后的dubboadmin压缩
mv dubboadmin.war /tmp
zip -r dubboadmin.war dubboadmin/
(2)准备tomcat的配置文件server.xml,更改tomcat数据目录
vim server.xml (该文件可通过拉起tomcat容器获取,这里只贴出更改内容)
<Host appBase="/data/tomcat/webapps" autoDeploy="true" name="localhost" unpackWARs="true">
(3)准备logging.properties
vim logging.properties
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
handlers = 1catalina.org.apache.juli.AsyncFileHandler, 2localhost.org.apache.juli.AsyncFileHandler, 3manager.org.apache.juli.AsyncFileHandler, 4host-manager.org.apache.juli.AsyncFileHandler, java.util.logging.ConsoleHandler
.handlers = 1catalina.org.apache.juli.AsyncFileHandler, java.util.logging.ConsoleHandler
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
1catalina.org.apache.juli.AsyncFileHandler.level = FINE
1catalina.org.apache.juli.AsyncFileHandler.directory = /data/tomcat/logs
1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.
2localhost.org.apache.juli.AsyncFileHandler.level = FINE
2localhost.org.apache.juli.AsyncFileHandler.directory = /data/tomcat/logs
2localhost.org.apache.juli.AsyncFileHandler.prefix = localhost.
3manager.org.apache.juli.AsyncFileHandler.level = FINE
3manager.org.apache.juli.AsyncFileHandler.directory = /data/tomcat/logs
3manager.org.apache.juli.AsyncFileHandler.prefix = manager.
4host-manager.org.apache.juli.AsyncFileHandler.level = FINE
4host-manager.org.apache.juli.AsyncFileHandler.directory = /data/tomcat/logs
4host-manager.org.apache.juli.AsyncFileHandler.prefix = host-manager.
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.AsyncFileHandler
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.AsyncFileHandler
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 4host-manager.org.apache.juli.AsyncFileHandler
# For example, set the org.apache.catalina.util.LifecycleBase logger to log
# each component that extends LifecycleBase changing state:
#org.apache.catalina.util.LifecycleBase.level = FINE
# To see debug messages in TldLocationsCache, uncomment the following line:
#org.apache.jasper.compiler.TldLocationsCache.level = FINE
(4)准备catalina.sh (添加启动参数,该文件可通过拉起tomcat容器获取,这里之贴出更改内容)
vim catalina.sh
JAVA_OPTS="-server -Xms512m -Xmx512m -Xss512k -Xmn1g -XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2 -XX:PermSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"
(5)准备tomcat运行脚本run_tomcat.sh
vim run_tomcat.sh
#!/bin/bash
su - nginx -c "/apps/tomcat/bin/catalina.sh start"
su - nginx -c "tail -f /etc/hosts"
chmod a+x run_tomcat.sh #添加可执行权限,如果不添加,容器内可能无法执行
3、编写Dockerfile(添加nginx用户、为tomcat添加主配置文件、启动脚本、tomcat运行脚本、添加dubboadmin到tomcat数据目录下、解压war包(war不会自动解压))
vim Dockerfile
#Dubbo dubboadmin
#FROM harbor.magedu.local/pub-images/tomcat-base:v8.5.43
FROM harbor.magedu.local/pub-images/tomcat-base:v8.5.43
MAINTAINER "957464230@qq.com"
RUN yum install unzip -y
ADD server.xml /apps/tomcat/conf/server.xml
ADD logging.properties /apps/tomcat/conf/logging.properties
ADD catalina.sh /apps/tomcat/bin/catalina.sh
ADD run_tomcat.sh /apps/tomcat/bin/run_tomcat.sh
ADD dubboadmin.war /data/tomcat/webapps/dubboadmin.war
RUN cd /data/tomcat/webapps && unzip dubboadmin.war && rm -rf dubboadmin.war && useradd nginx -u 2088 && chown -R nginx.nginx /data /apps
EXPOSE 8080 8443
CMD ["/apps/tomcat/bin/run_tomcat.sh"]
4、编写构建镜像脚本
vim build-command.sh
#!/bin/bash
TAG=$1
docker build -t harbor.magedu.local/magedu/dubboadmin:${TAG} .
sleep 3
docker push harbor.magedu.local/magedu/dubboadmin:${TAG}
5、运行脚本,构建镜像
bash build-command.sh v1
9.8.2 K8S部署
9.8.2.1 K8S部署provider
1、创建存放文件的目录
mkdir -p /root/k8s-data/yaml/magedu/dubbo/provider
cd /root/k8s-data/yaml/magedu/dubbo/provider
2、编写yaml文件
vim provider.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-provider
name: magedu-provider-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-provider
template:
metadata:
labels:
app: magedu-provider
spec:
containers:
- name: magedu-provider-container
image: harbor.magedu.local/magedu/dubbo-demo-provider:v1
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 20880
protocol: TCP
name: http
---
kind: Service #生产者一般情况下不需要service,消费者会直接从注册中心获取生产者ip地址,该service配置可忽略
apiVersion: v1
metadata:
labels:
app: magedu-provider
name: magedu-provider-spec
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 20880
#nodePort: 30001
selector:
app: magedu-provider
创建容器
kubectl apply -f provider.yaml
查看provider容器
9.8.2.2 K8S部署consumer
1、创建存放文件的目录
mkdir -p /root/k8s-data/yaml/magedu/dubbo/consumer
cd /root/k8s-data/yaml/magedu/dubbo/consumer
2、编写yaml文件
vim consumer.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-consumer
name: magedu-consumer-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-consumer
template:
metadata:
labels:
app: magedu-consumer
spec:
containers:
- name: magedu-consumer-container
image: harbor.magedu.local/magedu/dubbo-demo-consumer:v1
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
---
kind: Service #消费者一般情况下不需要service,会直接从注册中心回去生产者的ip地址,该service配置可忽略
apiVersion: v1
metadata:
labels:
app: magedu-consumer
name: magedu-consumer-server
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
#nodePort: 30001
selector:
app: magedu-consumer
3、创建容器
kubectl apply -f consumer.yaml
4、查看consumer容器
5、验证:
(1)查看provider容器日志,可以看到调用关系。每隔2s调用一次
kubectl exec -it magedu-provider-deployment-75d57b7b6c-bbt7m bash -n magedu
tail -f /apps/dubbo/provider/logs/stdout.log
(2)上面截图中的10.200.107.210正是consumer地址,说明注册中心已经启用,消费者可以直接从注册中心获取生产者地址进行服务调用
9.8.2.3 K8S部署dubboadmin
1、创建存放文件的目录
mkdir -p /root/k8s-data/yaml/magedu/dubbo/dubboadmin
cd /root/k8s-data/yaml/magedu/dubbo/dubboadmin
2、编写yaml文件
vim dubboadmin.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-dubboadmin
name: magedu-dubboadmin-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-dubboadmin
template:
metadata:
labels:
app: magedu-dubboadmin
spec:
containers:
- name: magedu-dubboadmin-container
image: harbor.magedu.local/magedu/dubboadmin:v1
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-dubboadmin
name: magedu-dubboadmin-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
nodePort: 31080 #暴露端口,以供外部访问
selector:
app: magedu-dubboadmin
3、创建容器
kubectl apply -f dubboadmin.yaml
4、查看dubboadmin容器
5、验证:
(1)浏览器输入:172.31.7.112:31080
账号/密码:root/root
(2)访问首页:
(3)查看服务:
文章评论