11 k8s 项目迁移 简单版


部署前期

  1. 准备工作 与 注意事项
  2. 准备基础镜像 并 推送到 镜像仓库
  3. 部署php/java项目

准备工作

  1. 部署的项目情况
    • 1、业务架构及服务 (dubbo、spring cloud)
    • 2、第三方服务 mysql,redis,zookeeper,eruka,mq
    • 3、服务之间怎么通信?
    • 4、资源消耗:硬件,带宽
  1. 部署项目时,用到的k8s资源
    • 1、namespace 不同的项目隔离 , 或者隔离不同的环境(test,prod,dev)
    • 2、无状态应用部署 (deployment)
    • 3、有状态应用部署 (statefulset,pv,pvc)
    • 4、发布项目暴露外部访问(service,ingress)
    • 5、信息存储 secret,configmap
  1. 准备基础镜像
1
2
3
[root@k8s-node2 nfs]# docker search lizhenliang
lizhenliang/nginx-php
lizhenliang/tomcat
  1. 编排部署
    • 1、编写yaml文件
  1. 工作流程
    • 1、kubectl -> yaml -> 镜像仓库拉取镜像 -> service(集群内部),ingresss -> 暴露给外部访问

部署 Java 应用

制作镜像

  1. 如果有cicd环境 自动完成 (代码拉取->代码编译构建->镜像打包->推送到镜像仓库)
  2. 没有 就手动构建
  3. 镜像为交付物

准备 pv 和 pvc

安装 nfs 服务

  1. 选定 172.17.70.254 作为 nfs 服务端
1
2
# 安装 nfs 所有node都需要安装 
[root@k8s-node2 nfs]# yum install nfs-utils -y
1
2
3
4
5
6
7
# 配置共享目录
[root@k8s-node2 ifs]# mkdir -p /ifs/kubernetes/
[root@k8s-node2 nfs]# vim /etc/exports
/ifs/kubernetes *(rw,no_root_squash)

# 启动服务
[root@k8s-node2 ifs]# systemctl start nfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 如过遇到nfs无法启动的检查步骤
[root@k8s-node2 ifs]# find /etc/ -name '*rpcbind.socket*'
/etc/systemd/system/sockets.target.wants/rpcbind.socket

[root@k8s-node2 ifs]# vim /etc/systemd/system/sockets.target.wants/rpcbind.socket

[Unit]
Description=RPCbind Server Activation Socket

[Socket]
ListenStream=/var/run/rpcbind.sock

# RPC netconfig can't handle ipv6/ipv4 dual sockets
BindIPv6Only=ipv6-only
#ListenStream=0.0.0.0:111
ListenDatagram=0.0.0.0:111
#ListenStream=[::]:111 # 如果监听了ipv6地址,将这一行注释即可
ListenDatagram=[::]:111

[Install]
WantedBy=sockets.target

# 重载一下 再启动
[root@k8s-node2 ifs]# systemctl daemon-reload
[root@k8s-node2 ifs]# systemctl restart rpcbind.socket
[root@k8s-node2 ifs]# systemctl start nfs

基于nfs 配置 PV 动态供给

1
2
3
4
5
6
7
8
# 上传nfs-client 修改IP地址为nfs服务端地址
# 由于k8s不支持 nfs的StorageClass 所有这些文件要从官网下载
# https://github.com/kubernetes-incubator/external-storage
[root@k8s-master1 nfs-client]# ls -l
total 12
-rw-r--r-- 1 root root 225 Nov 30 20:50 class.yaml # StorageClass 动态pv创建
-rw-r--r-- 1 root root 993 Dec 13 09:25 deployment.yaml # 创建 nfs-client pod
-rw-r--r-- 1 root root 1526 Nov 30 20:50 rbac.yaml # nfs pod 访问 apiserver
1
2
3
4
5
6
# 创建
[root@k8s-master1 nfs-client]# kubectl apply -f .

[root@k8s-master1 nfs-client]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-5dd6f66f47-99w7k 1/1 Running 0 20s
1
2
3
4
5
6
7
8
9
[root@k8s-master1 nfs-client]# cat class.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
# 指定 StorageClass 创建 pv 的名称,创建项目的时候用到
name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
archiveOnDelete: "true"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[root@k8s-master1 nfs-client]# cat deployment.yaml 

apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
# nfs地址
- name: NFS_SERVER
value: 172.17.70.254
# 共享目录
- name: NFS_PATH
value: /ifs/kubernetes
volumes:
- name: nfs-client-root
nfs:
server: 172.17.70.254
path: /ifs/kubernetes

部署 harbor仓库

1
2
3
4
5
6
7
# 该主机也需要二进制安装docker 
[root@k8s-master2 src]# scp root@172.17.70.254:/opt/src/docker-18.09.6.tgz .
[root@k8s-master2 src]# scp root@172.17.70.254:/usr/lib/systemd/system/docker.service .
[root@k8s-master2 src]# scp root@172.17.70.254:/etc/docker/daemon.json .
[root@k8s-master2 src]# tar -zxvf docker-18.09.6.tgz
[root@k8s-master2 src]# mv docker/* /usr/bin/
[root@k8s-master2 src]# mv docker.service /usr/lib/systemd/system
1
2
3
4
5
6
7
8
[root@k8s-master2 src]# mkdir -p /etc/docker
[root@k8s-master2 src]# mv daemon.json /etc/docker/

[root@k8s-master2 src]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["http://bc437cce.m.daocloud.io"], # 镜像加速
"insecure-registries": ["172.17.70.252"] # 可信任IP 回头换成harbor地址
}
1
2
3
[root@k8s-node1 src]# systemctl start docker
[root@k8s-node1 src]# systemctl enable docker
[root@k8s-node1 src]# docker info
1
2
3
4
# 上传文件
[root@k8s-master2 src]# ls -l
-rw-r--r-- 1 root root 17237024 Nov 13 14:33 docker-compose-Linux-x86_64
-rw-r--r-- 1 root root 580462944 Nov 13 14:34 harbor-offline-installer-v1.8.4.tgz
1
2
3
4
5
# 部署 compose
[root@k8s-master2 src]# mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
[root@k8s-master2 src]# chmod +x /usr/local/bin/docker-compose
[root@k8s-master2 src]# docker-compose -version
docker-compose version 1.25.0dev, build bc57a1bd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 部署 harbor
[root@k8s-master2 src]# tar -xf harbor-offline-installer-v1.8.4.tgz -C /opt/
[root@k8s-master2 src]# cd /opt/harbor/
# 修改主机名和管理员密码、数据库密码
hostname: 172.17.70.252 # http
harbor_admin_password: 123456 # 访问密码
database:
password: 123456

# 准备
[root@k8s-master2 src]# ./prepare
# 安装
[root@k8s-master2 src]# ./install.sh
# web访问
http://123.56.14.192
# 列出
docker-compose ps

免https使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@Docker harbor]# vim /etc/docker/daemon.json 
# 写入进项仓库 IP+port

{
"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
"insecure-registries": ["172.17.70.252"]
}

# 重启docker
systemctl daemon-reload
systemctl restart docker.service

[root@Docker nginx]# docker info
Insecure Registries:
172.17.70.252
127.0.0.0/8

登录

1
2
3
4
# 两个node节点都先登录下 好下载基础镜像
[root@k8s-node1 cfg]# docker login 172.17.70.252
Username: admin
Password:

下载 pod基础镜像 并上传到私有仓库

1
2
3
4
[root@k8s-master2 opt]# docker pull lizhenliang/pause-amd64:3.0 
[root@k8s-master2 opt]# docker tag lizhenliang/pause-amd64:3.0 172.17.70.252/base/pause-amd64:3.0
[root@k8s-master2 opt]# docker login 172.17.70.252
[root@k8s-master2 opt]# docker push 172.17.70.252/base/pause-amd64:3.0

构建基础镜像

  1. nginx
  2. php
  3. tomcat

构建项目镜像

安装Git

1
[root@k8s-node3 opt]# yum install git

下载项目

1
2
3
4
5
6
7
8
9
10
11
12
[root@k8s-node3 opt]# cd /opt/
[root@k8s-node3 opt]# git clone https://github.com/lizhenliang/tomcat-java-demo.git


[root@k8s-node3 opt]# ls -l
total 32
drwxr-xr-x 2 root root 4096 Nov 20 16:33 db # 数据库sql文件
-rw-r--r-- 1 root root 148 Nov 20 16:33 Dockerfile # 构建镜像
-rw-r--r-- 1 root root 11357 Nov 20 16:33 LICENSE
-rw-r--r-- 1 root root 1930 Nov 20 16:33 pom.xml # maven构建环境
-rw-r--r-- 1 root root 270 Nov 20 16:33 README.md
drwxr-xr-x 3 root root 4096 Nov 20 16:33 src # 源码目录

编译源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 安装 jdk 和 maven 环境
[root@k8s-node3 tomcat-java-demo]# yum search openjdk
[root@k8s-node3 tomcat-java-demo]# yum install java-1.8.0-openjdk maven

# mvn 编译
[root@k8s-node3 tomcat-java-demo]# mvn clean package -Dmaven.test.skip=true
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.882s
[INFO] Finished at: Wed Nov 20 17:08:13 CST 2019
[INFO] Final Memory: 22M/95M
[INFO] ------------------------------------------------------------------------

# 查看生成的war包
[root@k8s-node3 tomcat-java-demo]# ls
db Dockerfile LICENSE pom.xml README.md src target
[root@k8s-node3 tomcat-java-demo]# cd target/
[root@k8s-master2 target]# ls -l *.war
-rw-r--r-- 1 root root 18265402 Nov 20 17:08 ly-simple-tomcat-0.0.1-SNAPSHOT.war

构建项目镜像

1
2
3
4
5
6
7
# 引用了老师的tomcat镜像运行环境
[root@k8s-master2 tomcat-java-demo]# vim Dockerfile

FROM lizhenliang/tomcat
LABEL maintainer www.ctnrs.com
RUN rm -rf /usr/local/tomcat/webapps/*
ADD target/*.war /usr/local/tomcat/webapps/ROOT.war
1
2
3
4
5
6
7
8
9
# 构建镜像
[root@k8s-master2 tomcat-java-demo]# docker build -t 172.17.70.252/project/java-demo .
[root@k8s-master2 tomcat-java-demo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
172.17.70.252/project/java-demo latest f656fe851ad7 24 seconds ago 406M

# 推送到镜像仓库
[root@k8s-master2 tomcat-java-demo]# docker login 172.17.70.252
[root@k8s-master2 tomcat-java-demo]# docker push 172.17.70.252/project/java-demo

无状态部署 tomcat

  1. tomcat
    • deployment
    • service
    • ingress
    • namespace # 逻辑项目隔离

创建 命名空间

1
2
3
4
5
6
[root@k8s-master1 java-demo]# vim namespace.yaml 

apiVersion: v1
kind: Namespace
metadata:
name: test
1
2
3
4
5
6
7
8
9
10
11
12
[root@k8s-master1 java-demo]# kubectl apply -f namespace.yaml 
namespace/test created

[root@k8s-master1 java-demo]# kubectl get ns
NAME STATUS AGE
default Active 8d
ingress-nginx Active 8d
kube-node-lease Active 8d
kube-public Active 8d
kube-system Active 8d
kubernetes-dashboard Active 8d
test Active 19s

部署 deployment

1
2
3
4
5
6
7
8
9
10
# registry-pull-secret 创建仓库凭证

[root@k8s-master1 java-demo]# kubectl create secret docker-registry registry-pull-secret --docker-username=admin --docker-password=lx@68328153 --docker-email=253911339@qq.com --docker-server=172.17.70.252 -n test

secret/registry-pull-secret created

[root@k8s-master1 java-demo]# kubectl get secret -n test
NAME TYPE DATA AGE
default-token-mnnbn kubernetes.io/service-account-token 3 14m
registry-pull-secret kubernetes.io/dockerconfigjson 1 12s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
[root@k8s-master1 templates]# vim /opt/java-demo/deployment.yaml 

apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-java-demo
namespace: test
spec:
replicas: 3
selector:
matchLabels:
project: www
app: java-demo
template:
metadata:
labels:
# 项目标签
project: www
app: java-demo
spec:
# 镜像仓库凭据
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: tomcat
image: 172.17.70.252/project/java-demo:latest
# Always 每次创建 Pod 都会重新拉取一次镜像
imagePullPolicy: Always
ports:
- containerPort: 8080
name: web
protocol: TCP
resources:
requests:
cpu: 0.5
memory: 1Gi
limits:
cpu: 1
memory: 2Gi
# 健康检查
livenessProbe:
httpGet:
path: /
port: 8080
# 容器启动60秒后 开始健康检查
initialDelaySeconds: 60
timeoutSeconds: 20
# 健康检查,检查失败,k8s会把Pod从service endpoints中剔除
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 20
1
2
3
4
5
6
# 创建启动
[root@k8s-master1 java-demo]# kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
tomcat-java-demo-d5d9c46cb-7zw4h 0/1 Running 0 7s
tomcat-java-demo-d5d9c46cb-lltt5 0/1 Running 0 7s
tomcat-java-demo-d5d9c46cb-qbc9g 0/1 Running 0 7s

项目发布 service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@k8s-master1 java-demo]# vim service.yaml 

apiVersion: v1
kind: Service
metadata:
name: tomcat-java-demo
namespace: test
spec:
selector:
project: www
app: java-demo
ports:
- name: web
port: 80
targetPort: 8080
type: NodePort
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建并测试
[root@k8s-master1 java-demo]# kubectl apply -f service.yaml
service/tomcat-java-demo created

[root@k8s-master1 java-demo]# kubectl get svc,ep -n test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/tomcat-java-demo NodePort 10.0.0.72 <none> 80:31193/TCP 10s

NAME ENDPOINTS AGE
endpoints/tomcat-java-demo 10.244.0.62:8080,10.244.1.72:8080,10.244.2.95:8080 10s

[root@k8s-master1 java-demo]# curl -I 10.0.0.72
HTTP/1.1 200
Content-Type: text/html;charset=utf-8
Content-Language: en-US
Content-Length: 2538
Date: Wed, 25 Dec 2019 07:58:37 GMT

暴露项目 Ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@k8s-master1 java-demo]# vim ingress.yaml 

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: tomcat-java-demo
namespace: test
spec:
rules:
- host: java.ctnrs.com
http:
paths:
- path: /
backend:
# 对应 servicename
serviceName: tomcat-java-demo
servicePort: 80
1
2
3
4
5
6
[root@k8s-master1 java-demo]# kubectl apply -f ingress.yaml 
ingress.extensions/tomcat-java-demo created

[root@k8s-master1 java-demo]# kubectl get ing -n test
NAME HOSTS ADDRESS PORTS AGE
tomcat-java-demo java.ctnrs.com 80 103s

测试访问

1
2
3
4
5
[root@k8s-master1 java-demo]# cat /etc/hosts

39.106.100.108 java.ctnrs.com
39.106.168.181 java.ctnrs.com
60.205.217.112 java.ctnrs.com

有状态部署 mysql

  1. mysql
    • statefulset
    • Headless Service (dns绑定)
    • pv,pvc (stotageclass pv自动供给)
1
2
3
# Headless Service
常规 Service:一组POD的访问策略,提供负载均衡服务发现
Headless Service: 不需要Cluster-IP,他会直接绑定到PODIP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
[root@k8s-master1 java-demo]# vim mysql.yaml 

apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: test
spec:
ports:
- port: 3306
name: mysql
clusterIP: None
selector:
app: mysql-public

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
namespace: test
spec:
serviceName: "mysql"
selector:
matchLabels:
app: mysql-public
template:
metadata:
labels:
app: mysql-public
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
- name: MYSQL_DATABASE
value: test
ports:
- containerPort: 3306
volumeMounts:
- mountPath: "/var/lib/mysql"
name: mysql-data
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteMany"]
# 动态pv name
storageClassName: "managed-nfs-storage"
resources:
requests:
storage: 2Gi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建并测试
[root@k8s-master1 java-demo]# kubectl apply -f mysql.yaml

[root@k8s-master1 java-demo]# kubectl get pods,svc -n test
NAME READY STATUS RESTARTS AGE
pod/db-0 1/1 Running 0 31s
pod/tomcat-java-demo-d5d9c46cb-7zw4h 1/1 Running 0 45m
pod/tomcat-java-demo-d5d9c46cb-lltt5 1/1 Running 0 45m
pod/tomcat-java-demo-d5d9c46cb-qbc9g 1/1 Running 0 45m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mysql ClusterIP None <none> 3306/TCP 73s
service/tomcat-java-demo NodePort 10.0.0.72 <none> 80:31193/TCP 38m

[root@k8s-master1 java-demo]# kubectl describe pod db-0 -n test

[root@k8s-master1 java-demo]# kubectl get pv,pvc -n test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 登录测试
[root@k8s-master1 java-demo]# kubectl exec -it db-0 bash -n test
root@db-0:/# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.28 MySQL Community Server (GPL)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)

导入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# copy文件
[root@k8s-node3 db]# scp tables_ly_tomcat.sql root@172.17.70.251:/opt/java-demo

# 上传到容器
[root@k8s-master1 java-demo]# kubectl cp tables_ly_tomcat.sql db-0:/tmp -n test
[root@k8s-master1 java-demo]# kubectl exec -it db-0 bash -n test
root@db-0:/# mysql -uroot -p
mysql> source /tmp/tables_ly_tomcat.sql;

# 查看
mysql> use test;
Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| user |
+----------------+
1 row in set (0.01 sec)

mysql> desc user;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(100) | NO | | NULL | |
| age | int(3) | NO | | NULL | |
| sex | char(1) | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

修改代码 数据库连接地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 修改源码 然后重新打包镜像
# 密码不要忘记修改 因为是连库串
# nslookup mysql.test
# ping db-0.mysql.test
# db-0.service名字.命名空间
# db-0.mysql.test
# 通过这个地址 连接mysqlpod的固定地址 这样即使pod销毁了地址不变

[root@k8s-node3 tomcat-java-demo]# vim src/main/resources/application.yml
...
datasource:
url: jdbc:mysql://db-0.mysql.test:3306/test?characterEncoding=utf-8
username: root
password: 123456

...

# 重新打包镜像部署 版本号变更
[root@k8s-node3 tomcat-java-demo]# mvn clean package -Dmaven.test.skip=true
[root@k8s-node3 tomcat-java-demo]# docker build -t 172.17.70.252/project/java-demo:1.0.1 .
[root@k8s-node3 tomcat-java-demo]# docker push 172.17.70.252/project/java-demo:1.0.1

# 重新部署 deployment
# 滚动更新时间跟 健康检查有关
[root@k8s-master1 java-demo]# vim deployment.yaml
...
containers:
- name: tomcat
image: 172.17.70.252/project/java-demo:1.0.1
...

[root@k8s-master1 java-demo]# kubectl delete -f deployment.yaml
[root@k8s-master1 java-demo]# kubectl apply -f deployment.yaml

[root@k8s-master1 java-demo]# kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
db-0 1/1 Running 0 38m
tomcat-java-demo-54d46868df-7vjs8 0/1 Running 0 5s
tomcat-java-demo-54d46868df-bhcsp 0/1 Running 0 5s
tomcat-java-demo-54d46868df-mfjlc 0/1 Running 0 5s


# 检查连库文件是否变更
[root@k8s-master1 java-demo]# kubectl exec -it tomcat-java-demo-54d46868df-7vjs8 bash -n test
[root@tomcat-java-demo-54d46868df-7vjs8 tomcat]# vi webapps/ROOT/WEB-INF/classes/application.yml

# 页面添加后 查看数据库数据
root@db-0:/# mysql -uroot -p --default-character-set=utf8
Enter password:
mysql> use test;
mysql> select * from user;
+----+-----------+-----+------+
| id | name | age | sex |
+----+-----------+-----+------+
| 1 | 哈哈哈 | 18 | F |
+----+-----------+-----+------+
1 row in set (0.00 sec)

部署 PHP 项目

  1. 项目源码地址
1
https://github.com/lizhenliang/php-demo

拉取项目源码

1
2
3
# 拉取项目源码
[root@k8s-node3 harbor]# cd /opt/
[root@k8s-node3 opt]# git clone https://github.com/lizhenliang/php-demo.git

数据库配置

1
2
3
4
# 共用之前java创建的mysql数据库
# 地址: db-0.mysql.test
# username: root
# password: 123456
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@k8s-node3 php-demo]# vim /opt/php-demo/wp-config.php 

/** WordPress数据库的名称 */
define('DB_NAME', 'test');

/** MySQL数据库用户名 */
define('DB_USER', 'root');

/** MySQL数据库密码 */
define('DB_PASSWORD', '123456');

/** MySQL主机 */
define('DB_HOST', 'db-0.mysql.test');

创建镜像

1
2
3
# 创建镜像
[root@k8s-node3 php-demo]# cd /opt/php-demo/
[root@k8s-node3 php-demo]# docker build -t 172.17.70.252/project/php-demo:1.0 .
1
2
# 推送镜像到镜像仓库
[root@k8s-node3 php-demo]# docker push 172.17.70.252/project/php-demo:1.0

创建命名空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@k8s-master1 php-demo]# vim namespace.yaml 

apiVersion: v1
kind: Namespace
metadata:
name: test

[root@k8s-master1 php-demo]# kubectl apply -f namespace.yaml
namespace/test created
[root@k8s-master1 php-demo]# kubectl get ns
NAME STATUS AGE
default Active 9d
ingress-nginx Active 9d
kube-node-lease Active 9d
kube-public Active 9d
kube-system Active 9d
kubernetes-dashboard Active 9d
test Active 3s

创建仓库凭证

1
2
3
4
5
6
7
[root@k8s-master1 php-demo]# kubectl create secret docker-registry registry-pull-secret --docker-username=admin --docker-password=lx@68328153 --docker-email=253911339@qq.com --docker-server=172.17.70.252 -n test
secret/registry-pull-secret created

[root@k8s-master1 php-demo]# kubectl get secret -n test
NAME TYPE DATA AGE
default-token-nh896 kubernetes.io/service-account-token 3 4m15s
registry-pull-secret kubernetes.io/dockerconfigjson 1 6s

创建 deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[root@k8s-master1 php-demo]# vim deployment.yaml 

apiVersion: apps/v1
kind: Deployment
metadata:
name: php-demo
namespace: test
spec:
replicas: 3
selector:
matchLabels:
project: www
app: php-demo
template:
metadata:
labels:
project: www
app: php-demo
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: nginx
image: 172.17.70.252/project/php-demo:1.0
imagePullPolicy: Always
ports:
- containerPort: 80
name: web
protocol: TCP
resources:
requests:
cpu: 0.5
memory: 256Mi
limits:
cpu: 1
memory: 1Gi
livenessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 6
timeoutSeconds: 20
readinessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 6
timeoutSeconds: 20
1
2
3
4
5
[root@k8s-master1 php-demo]# kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
php-demo-7d685c9cb6-7qhgq 1/1 Running 0 41s
php-demo-7d685c9cb6-h4b6b 1/1 Running 0 41s
php-demo-7d685c9cb6-kdwr5 1/1 Running 0 41s

创建 service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@k8s-master1 php-demo]# vim service.yaml 

apiVersion: v1
kind: Service
metadata:
name: php-demo
namespace: test
spec:
selector:
project: www
app: php-demo
ports:
- name: web
port: 80
targetPort: 80
type: NodePort
1
2
3
4
5
6
7
8
9
[root@k8s-master1 php-demo]# kubectl apply -f service.yaml 
service/php-demo created

[root@k8s-master1 php-demo]# kubectl get svc,ep -n test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/php-demo NodePort 10.0.0.39 <none> 80:31677/TCP 14s

NAME ENDPOINTS AGE
endpoints/php-demo 10.244.0.67:80,10.244.1.75:80,10.244.2.101:80 14s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建 ingress
[root@k8s-master1 php-demo]# vim ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: php-demo
namespace: test
spec:
rules:
- host: php.ctnrs.com
http:
paths:
- path: /
backend:
serviceName: php-demo
servicePort: 80
1
2
[root@k8s-master1 php-demo]# kubectl apply -f ingress.yaml 
ingress.extensions/php-demo created

创建 mysql 有状态应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
[root@k8s-master1 php-demo]# vim mysql.yaml 

apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: test
spec:
ports:
- port: 3306
name: mysql
clusterIP: None
selector:
app: mysql-public

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
namespace: test
spec:
serviceName: "mysql"
selector:
matchLabels:
app: mysql-public
template:
metadata:
labels:
app: mysql-public
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
- name: MYSQL_DATABASE
value: test
ports:
- containerPort: 3306
volumeMounts:
- mountPath: "/var/lib/mysql"
name: mysql-data
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteMany"]
# 动态pv name
storageClassName: "managed-nfs-storage"
resources:
requests:
storage: 2Gi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
[root@k8s-master1 php-demo]# kubectl apply -f mysql.yaml
service/mysql created
statefulset.apps/db created
[root@k8s-master1 php-demo]# kubectl get pods,svc -n test
NAME READY STATUS RESTARTS AGE
pod/db-0 1/1 Running 0 5s
pod/php-demo-7d685c9cb6-7qhgq 1/1 Running 0 10m
pod/php-demo-7d685c9cb6-h4b6b 1/1 Running 0 10m
pod/php-demo-7d685c9cb6-kdwr5 1/1 Running 0 10m

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mysql ClusterIP None <none> 3306/TCP 5s
service/php-demo NodePort 10.0.0.39 <none> 80:31677/TCP 7m53s

# 由于我之前测试删除了存储,所有这是个新的数据库
# 登录测试
[root@k8s-master1 java-demo]# kubectl exec -it db-0 bash -n test
root@db-0:/# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.28 MySQL Community Server (GPL)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)

测试域名访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 阿里云还没有屏蔽签测试域名
# 屏蔽了 测试 nodeIp+端口

39.106.100.108 php.ctnrs.com
39.106.168.181 php.ctnrs.com
60.205.217.112 php.ctnrs.com

[root@k8s-master1 php-demo]# kubectl get ing -n test
NAME HOSTS ADDRESS PORTS AGE
php-demo php.ctnrs.com 80 10m

[root@k8s-master1 php-demo]# kubectl get svc -n test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql ClusterIP None <none> 3306/TCP 6m1s
php-demo NodePort 10.0.0.39 <none> 80:31677/TCP 13m

39.106.100.108:31677

# 安装 会初始化数据到 mysql中
# 都是项目打包制作镜像时 填写好的配置