环境:OSE 3.0.1
0. 开始实验之前, 重置所有虚机,重置后会自动重新启动所有虚机
[kiosk@fundation0 ~]$ rht-vmctl reset all
1. 安装 OSE 3.0
1.1 OSE 3.0 安装先决条件
(1)确认 master 节点主机已经注册了必须的软件频道(node 节点主机也做此步)
[root@master ~]# yum repolist
(2)安装必要软件,一共 9 个软件(node 节点主机也做此步)
[root@master ~]# yum -y install docker wget git net-tools bind-utils iptables-services bridge-utils python-virtualenv gcc
(3)确认主机名和 IP 地址对应(node 节点主机也做此步)
[root@master ~]# host $(hostname -f)(node 节点主机也做此步)
(4)生成 SSH 无密码的公钥和私钥对
[root@master ~]# ssh-keygen -N ''
(5)复制 SSH 公钥到所有主机
[root@master ~]# ssh-copy-id root@node.pod0.example.com 口令 redhat
[root@master ~]# ssh-copy-id root@master.pod0.example.com 口令 redhat
(6)stop 并 disable NetworkManager 和 firewalld(node 节点主机也做此步)
[root@master ~]# systemctl stop NetworkManager
[root@master ~]# systemctl disable NetworkManager
[root@master ~]# systemctl stop firewalld
[root@master ~]# systemctl disable firewalld
1.2. 配置 docker daemon
(1)安装 private registry 证书作为受信证书(node 节点主机也做此步)
[root@master ~]# yum -y install ca-certificates
[root@master ~]# update-ca-trust enable
[root@master ~]# scp root@workstation.pod0.example.com:/etc/pki/tls/certs/self.crt /etc/pki/ca-trust/source/anchors/
[root@master ~]# update-ca-trust extract
(2)在继续下一步之前, 确认停止 docker(node 节点主机也做此步)
[root@master ~]# systemctl stop docker
(3)修改文件, 确认只搜索 private registry(node 节点主机也做此步)
[root@master ~]# vi /etc/sysconfig/docker
#ADD_REGISTRY='--add-registry registry.access.redhat.com'
ADD_REGISTRY='--add-registry workstation.pod0.example.com:5000'
BLOCK_REGISTRY='--block-registry public --block-registry registry.access.redhat.com'
(4)创建新文件, 指定容器(非持久存储)使用 LVM thinpool(node 节点主机也做此步)
[root@master ~]# vi /etc/sysconfig/docker-storage-setup
DEVS=/dev/vdb
VG=docker-vg
SETUP_LVM_THIN_POOL=yes
(5)配置 LVM thinpool(node 节点主机也做此步)
[root@master ~]# lvmconf --disable-cluster
[root@master ~]# docker-storage-setup
(6)再次 start 并 enable docker(node 节点主机也做此步)
[root@master ~]# systemctl start docker
[root@master ~]# systemctl enable docker
1.3. 预取所有 OSE 以及运行时容器 images 到所有主机
(1)用脚本 pull 所有 images (node 节点主机也做此步)
[root@master ~]# /root/DO280/labs/lab-review/fetch.sh
fetch.sh 脚本内容如下:
#!/bin/bash
# OSE 3 containerized services images
# Needs version because the private repo do not have ":latest" tags
for image in \
openshift3/ose-haproxy-router openshift3/ose-deployer openshift3/ose-sti-builder openshift3/ose-sti-image-builder \
penshift3/ose-docker-builder openshift3/ose-pod openshift3/ose-docker-registry openshift3/ose-keepalived-ipfailover
do docker pull $image:v3.0.1.0; done
# OSE 3 runtime images
for image in \
openshift3/ruby-20-rhel7 openshift3/php-55-rhel7 openshift3/nodejs-010-rhel7 openshift3/mysql-55-rhel7 \
jboss-eap-6/eap-openshift
do docker pull $image; done
# sample images
for image in \
openshift/hello-openshift php-quote
do docker pull $image; done
重要说明:
(1)如果没有脚本, 搜索 openshift3, 然后再 pull 具体的 image (node 节点主机也做此步)
[root@master ~]# docker search openshift3
[root@master ~]# docker pull openshift3/ose-haproxy-router
(2)某些 images, 比如 xPaaS images 没有 openshift3 作为名字的一部分。
作为本实验, 记得下载 jboss-eap-6/eap-openshift image。
(3)不要搜索 openshift, 然后下载所有返回的 images, 因为大多数 images 来自社区, 没有经过认证。
[root@master ~]# docker search openshift
1.4. 运行 OSE 快速安装脚本
(1)解压
[root@master ~]# mkdir ose-installer ; cd ose-installer
[root@master ose-installer]# tar xzf /root/DO280/installers/oo-install-ose.tgz
(2)安装
[root@master ose-installer]# ./oo-install-ose
• 输入 Y 确认继续
• 回车确认 root 作为 ssh 访问用户
• 按任意键继续, 准备添加 master 主机名列表
• 安装程序会打开一个 vi 编辑器, 输入 master 主机名列表:
master.pod0.example.com
wq!保存
• 输入 Y 确认 master 主机名列表
• 按任意键继续, 准备添加 node 主机名列表, 注意 master 也是一种 node
• 安装程序会打开一个 vi 编辑器, 输入 node 主机名列表: (注意 master 也是一种 node, 并且已经添加了 master)
• 输入 node 主机名列表:
master.pod0.example.com // 已添加
node.pod0.example.com
wq!保存
• 输入 Y 确认 node 主机名列表
• 按任意键继续
• 安装程序会打开一个 vi 编辑器, 包含所有的 master 和 node 主机名和 IP 地址列表
确认无误后, wq!保存
• 输入 Y 确认继续
• 出现 The installation was successful!信息后, 按任意键继续
• 确认信息正确
• 如果一切正确, 输入 Y 开始安装
(3)安装完毕后, 检查主机状态
[root@master ~]# oc get nodes
(4)确认 openshift services 都正常启动了
[root@master ~]# systemctl status openshift-master
[root@master ~]# systemctl status openshift-node
[root@node ~]# systemctl status openshift-node
1.5. 修改 OSE image streams
S2I 时, 会从 registry pull images, 默认指向的地址是 redhat private registry, 需要修改成实验环境下的 registry。
[root@master ~]# oc edit is -n openshift
会打开一个 vi 编辑器, 执行如下替换
:%s/registry.access.redhat.com/workstation.pod0.example.com:5000
1.6. 使用 Apache htpasswd 作为 OSE 的认证方式
(1)安装 httpd-tools package
[root@master ~]# yum -y install httpd-tools
(2)修改 /etc/openshift/master/master-config.yaml
找到 oauthConfig 部分
增加一个 file 属性 /etc/openshift/openshift-passwd
kind 属性 替换 DenyAllPasswordIdentityProvider 为 HTPasswdPasswordIdentityProvider
(3)创建 /etc/openshift/openshift-passwd 文件
[root@master ~]# touch /etc/openshift/openshift-passwd
(4)重启 openshift-master
[root@master ~]# systemctl restart openshift-master
1.7. 发布 OSE router 和 internal registry
(1)配置 OSE master 使用正确的 DNS wild-card domain 名称
[root@master ~]# vi /etc/openshift/master/master-config.yaml
routingConfig
subdomain: cloudapps0.example.com
[root@master ~]# systemctl restart openshift-master
(2)创建 router service account
[root@master ~]# echo '{"kind":"ServiceAccount","apiVersion":"v1","metadata":{"name":"router"}}' | oc create -f -
(3)修改 privileged security context constraints (SCC), 加入 router service account
[root@master ~]# oc edit scc privileged
找到 users:,在其下面增加一个新用户 system:serviceaccount:default:router :
users:
- system:serviceaccount:default:router
- system:serviceaccount:openshift-infra:build-controller
注意:可以运行脚本 /root/DO280/labs/lab-review/router_scc.sh 创建 service account 并且加到 privileged SCC。
router_scc.sh 脚本内容如下:
#!/bin/bash
echo \
'{"kind":"ServiceAccount","apiVersion":"v1","metadata":{"name":"router"}}' \
| oc create -f -
oc get scc privileged -o yaml > scc_privileged.yaml
sed -i '
/users:/ a \
- system:serviceaccount:default:router
' scc_privileged.yaml
oc replace scc privileged -f scc_privileged.yaml
(4)发布默认的 HAProxy router
[root@master ~]# oadm router oserouter --credentials='/etc/openshift/master/openshift-router.kubeconfig' --images='openshift3/ose-haproxy-router:${version}' --service-account=router
确认 router pod 运行起来后, 再执行下一步
[root@master ~]# oc get pods
(5)发布 OSE internal container image registry
[root@master ~]# oadm registry --credentials=/etc/openshift/master/openshift-registry.kubeconfig --images='openshift3/ose-docker-registry:${version}'
确认 registry pod 运行起来后, 再执行下一步
[root@master ~]# oc get pods
1.8. 为 OSE internal registry 提供持久化存储
(1)安装并配置 NFS Server(master)和 NFS Client(node)
[root@master ~]# bash /root/DO280/labs/lab-review/config-nfs-server.sh
config-nfs-server.sh 脚本内容如下:
#!/bin/bash
# OSE 3.0.1.0 packages already add nfs-utils as dependency
#yum -y install nfs-utils
#ssh root@node yum -y install nfs-utils
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 111 -j ACCEPT
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2049 -j ACCEPT
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 20048 -j ACCEPT
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 50825 -j ACCEPT
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 53248 -j ACCEPT
sed -i '/COMMIT/ i \
# BEGIN NFS server \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 53248 -j ACCEPT \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 50825 -j ACCEPT \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 20048 -j ACCEPT \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2049 -j ACCEPT \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 111 -j ACCEPT \
# END NFS server' /etc/sysconfig/iptables
# DO NOT restart iptables. Restarting it looses rules added by docker and openshift-sdn
sed -i '
s/RPCMOUNTDOPTS=""/RPCMOUNTDOPTS="-p 20048"/
s/STATDARG=""/STATDARG="-p 50825"/
' /etc/sysconfig/nfs
echo '
fs.nfs.nlm_tcpport=53248
fs.nfs.nlm_udpport=53248
' >> /etc/sysctl.conf
modprobe nfsd
sysctl -p
for u in rpcbind nfs-server nfs-lock nfs-idmap; do
systemctl enable $u
systemctl start $u
done
setsebool -P virt_use_nfs=true
ssh root@node setsebool -P virt_use_nfs=true
(2)发布 OSE internal container image registry
[root@master ~]# mkdir -p /var/export/registryvol
[root@master ~]# chown nfsnobody:nfsnobody /var/export/registryvol
[root@master ~]# chmod 700 /var/export/registryvol
(3)Export 该目录
[root@master ~]# vi /etc/exports
增加一行内容如下:
/var/export/registryvol *(rw,async,all_squash)
(4)允许客户端访问
[root@master ~]# exportfs -a
(5)复制 PV 定义文件
[root@master ~]# cp /root/DO280/labs/lab-review/registry-volume.json /root
[root@master ~]# vi /root/registry-volume.json
修改内容如下:
"server": "master.pod0.example.com"
修改后的 registry-volume.json 的完整内容如下:
{
"apiVersion": "v1",
"kind": "PersistentVolume",
"metadata": {
"name": "registry-volume",
"labels": {
"deploymentconfig": "docker-registry"
}
},
"spec": {
"capacity": {
"storage": "10Gi"
},
"accessModes": [ "ReadWriteMany" ],
"nfs": {
"path": "/var/export/registryvol",
"server": "master.pod0.example.com"
}
}
}
说明: OpenShift Enterprise Developer Guide 有 YAML 格式的 PV 定义。
(6)创建 PV
[root@master ~]# oc create -f /root/registry-volume.json
1.9. 绑定 PV 到 registry pod
(1)创建 PVClaim
[root@master ~]# oc create -f /root/DO280/labs/lab-review/registry-pvclaim.json
registry-pvclaim.json 的完整内容如下:
{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"name": "registry-pvclaim",
"labels": {
"deploymentconfig": "docker-registry"
}
},
"spec": {
"accessModes": [ "ReadWriteMany" ],
"resources": {
"requests": {
"storage": "10Gi"
}
}
}
}
(2)确认 PVClaim 绑定到了 PV
[root@master ~]# oc get pvc
(3)修改 DeploymentConfig docker-registry to use the PVClaim:
[root@master ~]# oc volume dc docker-registry --add --overwrite -t persistentVolumeClaim --claim-name=registry-pvclaim --name=registry-storage
(4)修改 docker-registry dc 后,确认 DeploymentConfig docker-registry 启动了一个新的 registry pod
[root@master ~]# oc status
(5)确认 registry 工作正常
[root@master ~]# oc describe service docker-registry
(6)访问 registry API,确认 registry pod 工作正常
[root@master ~]# curl http://172.30.10.176:5000/healthz
2. 发布 Bookstore 应用
2.1. 创建用户 developer
(1)使用 htpasswd 创建用户
[root@master ~]# htpasswd -b /etc/openshift/openshift-passwd developer openshift
2.2. 创建 project 并增加 quota 限制
(1)安装 OSE client (workstation 主机)
[student@workstation ~]$ sudo yum -y install openshift
输入口令 student
(2)以 developer 账户登录 (workstation 主机)
[student@workstation ~]$ oc login -u developer -p openshift
由于是第一次登录,会询问 master 的信息, 输入 https://master.pod0.example.com:8443
并使用 insecure connections? (y/n): y
(3)创建 project bookstore (workstation 主机)
[student@workstation ~]$ oc new-project bookstore
(4)为 project bookstore 增加限制 quota (master 主机)
[root@master ~]# oc create -f /root/DO280/labs/lab-review/project-quotas.json -n bookstore
project-quotas.json 的完整内容如下:
{
"apiVersion": "v1",
"kind": "ResourceQuota",
"metadata": {
"name": "bookstore-project-quotas"
},
"spec": {
"hard": {
"memory": "16Gi",
"cpu": "6000m",
"pods": "6",
"services": "8",
"replicationcontrollers": "5",
"persistentvolumeclaims": "2"
}
}
}
(5)为 project bookstore 增加限制 limit (master 主机)
[root@master ~]# oc create -f /root/DO280/labs/lab-review/project-limits.json -n bookstore
project-limits.json 的完整内容如下:
{
"kind": "LimitRange",
"apiVersion": "v1",
"metadata": {
"name": "bookstore-project-limits"
},
"spec": {
"limits": [
{
"type": "Pod",
"max": {
"cpu": "500m",
"memory": "4Gi"
},
"min": {
"cpu": "200m",
"memory": "512Mi"
}
},
{
"type": "Container",
"max": {
"cpu": "500m",
"memory": "4Gi"
},
"min": {
"cpu": "200m",
"memory": "512Mi"
},
"default": {
"cpu": "200m",
"memory": "1.5Gi"
}
}
]
}
}
2.3. 查看并确认 application template 的参数 (全部在 workstation 主机)
(1)列出 template eap6-mysql-persistent-sti 的所有参数
[student@workstation ~]$ oc process --parameters eap6-mysql-persistent-sti -n openshift | sort
输出如下:
DB_DATABASE Database name
DB_USERNAME Database user name
DB_PASSWORD Database user password
EAP_HTTPS_SECRET The name of the secret containing the keystore file
EAP_HTTPS_KEYSTORE The name of the keystore file within the secret
EAP_HTTPS_NAME The name associated with the server certificate
EAP_HTTPS_PASSWORD The password for the keystore and certificate
GIT_URI Git source URI for application
VOLUME_CAPACITY Size of persistent storage for database volume
(2)导出 application template
[student@workstation ~]$ oc export template eap6-mysql-persistent-sti -o json -n openshift > eap6-mysql-persistent-sti.json
(3)分析导出的 template 文件 eap6-mysql-persistent-sti.json
[student@workstation ~]$ vim eap6-mysql-persistent-sti.json
检查如下参数配置:
◦ 2 个 pods: 一个是 application pod,一个是 database pod, 分别在各自的 DeploymentConfig 中配置。
◦ 1 个 BuildConfig:用来从 source code 生成 application image。
◦ 1 个 ImageStream:用来生成 application image。
◦ 2 个 services:一个是 application,一个是 database。
◦ 1 个额外的 service:用做 JBoss EAP clustering。
◦ 2 个 routes:全都是为了 application pod service,一个用 HTTP,一个用 HTTPS。
◦ 1 个 PVClaim:用做 database data volume。
eap6-mysql-persistent-sti.json 完整内容如下:
{
"kind": "Template",
"apiVersion": "v1",
"metadata": {
"name": "eap6-mysql-persistent-sti",
"creationTimestamp": null,
"annotations": {
"description": "Application template for EAP 6 MySQL applications with persistent storage built using STI.",
"iconClass": "icon-jboss"
}
},
"objects": [
{
"kind": "Service",
"apiVersion": "v1",
"spec": {
"ports": [
{
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"deploymentConfig": "${APPLICATION_NAME}"
}
},
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "The web server's http port."
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"spec": {
"ports": [
{
"port": 8443,
"targetPort": 8443
}
],
"selector": {
"deploymentConfig": "${APPLICATION_NAME}"
}
},
"metadata": {
"name": "secure-${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "The web server's https port."
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"spec": {
"ports": [
{
"port": 8888,
"targetPort": 8888
}
],
"portalIP": "None",
"selector": {
"deploymentConfig": "${APPLICATION_NAME}"
}
},
"metadata": {
"name": "${APPLICATION_NAME}-ping",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "Ping service for clustered applications."
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"spec": {
"ports": [
{
"port": 3306,
"targetPort": 3306
}
],
"selector": {
"deploymentConfig": "${APPLICATION_NAME}-mysql"
}
},
"metadata": {
"name": "${APPLICATION_NAME}-mysql",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "The database server's port."
}
}
},
{
"kind": "Route",
"apiVersion": "v1",
"id": "${APPLICATION_NAME}-http-route",
"metadata": {
"name": "${APPLICATION_NAME}-http-route",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "Route for application's http service."
}
},
"spec": {
"host": "${APPLICATION_HOSTNAME}",
"to": {
"name": "${APPLICATION_NAME}"
}
}
},
{
"kind": "Route",
"apiVersion": "v1",
"id": "${APPLICATION_NAME}-https-route",
"metadata": {
"name": "${APPLICATION_NAME}-https-route",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "Route for application's https service."
}
},
"spec": {
"host": "${APPLICATION_HOSTNAME}",
"to": {
"name": "secure-${APPLICATION_NAME}"
},
"tls": {
"termination": "passthrough"
}
}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
}
}
},
{
"kind": "BuildConfig",
"apiVersion": "v1",
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"source": {
"type": "Git",
"git": {
"uri": "${GIT_URI}",
"ref": "${GIT_REF}"
},
"contextDir": "${GIT_CONTEXT_DIR}"
},
"strategy": {
"type": "Source",
"sourceStrategy": {
"from": {
"kind": "ImageStreamTag",
"namespace": "openshift",
"name": "jboss-eap6-openshift:${EAP_RELEASE}"
}
}
},
"output": {
"to": {
"kind": "ImageStreamTag",
"name": "${APPLICATION_NAME}:latest"
}
},
"triggers": [
{
"type": "GitHub",
"github": {
"secret": "${GITHUB_TRIGGER_SECRET}"
}
},
{
"type": "Generic",
"generic": {
"secret": "${GENERIC_TRIGGER_SECRET}"
}
},
{
"type": "ImageChange",
"imageChange": {}
}
]
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"strategy": {
"type": "Recreate"
},
"triggers": [
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"${APPLICATION_NAME}"
],
"from": {
"kind": "ImageStream",
"name": "${APPLICATION_NAME}"
}
}
}
],
"replicas": 1,
"selector": {
"deploymentConfig": "${APPLICATION_NAME}"
},
"template": {
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"deploymentConfig": "${APPLICATION_NAME}",
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"serviceAccount": "eap-service-account",
"containers": [
{
"name": "${APPLICATION_NAME}",
"image": "${APPLICATION_NAME}",
"imagePullPolicy": "Always",
"volumeMounts": [
{
"name": "eap-keystore-volume",
"mountPath": "/etc/eap-secret-volume",
"readOnly": true
}
],
"readinessProbe": {
"exec": {
"command": [
"/bin/bash",
"-c",
"/opt/eap/bin/readinessProbe.sh"
]
}
},
"ports": [
{
"name": "http",
"containerPort": 8080,
"protocol": "TCP"
},
{
"name": "https",
"containerPort": 8443,
"protocol": "TCP"
},
{
"name": "ping",
"containerPort": 8888,
"protocol": "TCP"
}
],
"env": [
{
"name": "DB_SERVICE_PREFIX_MAPPING",
"value": "${APPLICATION_NAME}-mysql=DB"
},
{
"name": "DB_JNDI",
"value": "${DB_JNDI}"
},
{
"name": "DB_USERNAME",
"value": "${DB_USERNAME}"
},
{
"name": "DB_PASSWORD",
"value": "${DB_PASSWORD}"
},
{
"name": "DB_DATABASE",
"value": "${DB_DATABASE}"
},
{
"name": "TX_DATABASE_PREFIX_MAPPING",
"value": "${APPLICATION_NAME}-mysql=DB"
},
{
"name": "DB_MIN_POOL_SIZE",
"value": "${DB_MIN_POOL_SIZE}"
},
{
"name": "DB_MAX_POOL_SIZE",
"value": "${DB_MAX_POOL_SIZE}"
},
{
"name": "DB_TX_ISOLATION",
"value": "${DB_TX_ISOLATION}"
},
{
"name": "OPENSHIFT_DNS_PING_SERVICE_NAME",
"value": "${APPLICATION_NAME}-ping"
},
{
"name": "OPENSHIFT_DNS_PING_SERVICE_PORT",
"value": "8888"
},
{
"name": "EAP_HTTPS_KEYSTORE_DIR",
"value": "/etc/eap-secret-volume"
},
{
"name": "EAP_HTTPS_KEYSTORE",
"value": "${EAP_HTTPS_KEYSTORE}"
},
{
"name": "EAP_HTTPS_NAME",
"value": "${EAP_HTTPS_NAME}"
},
{
"name": "EAP_HTTPS_PASSWORD",
"value": "${EAP_HTTPS_PASSWORD}"
},
{
"name": "HORNETQ_CLUSTER_PASSWORD",
"value": "${HORNETQ_CLUSTER_PASSWORD}"
},
{
"name": "HORNETQ_QUEUES",
"value": "${HORNETQ_QUEUES}"
},
{
"name": "HORNETQ_TOPICS",
"value": "${HORNETQ_TOPICS}"
}
]
}
],
"volumes": [
{
"name": "eap-keystore-volume",
"secret": {
"secretName": "${EAP_HTTPS_SECRET}"
}
}
]
}
}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "${APPLICATION_NAME}-mysql",
"labels": {
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"strategy": {
"type": "Recreate"
},
"triggers": [
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"${APPLICATION_NAME}-mysql"
],
"from": {
"kind": "ImageStreamTag",
"namespace": "openshift",
"name": "mysql:latest"
}
}
}
],
"replicas": 1,
"selector": {
"deploymentConfig": "${APPLICATION_NAME}-mysql"
},
"template": {
"metadata": {
"name": "${APPLICATION_NAME}-mysql",
"labels": {
"deploymentConfig": "${APPLICATION_NAME}-mysql",
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"containers": [
{
"name": "${APPLICATION_NAME}-mysql",
"image": "mysql",
"imagePullPolicy": "Always",
"ports": [
{
"containerPort": 3306,
"protocol": "TCP"
}
],
"volumeMounts": [
{
"mountPath": "/var/lib/mysql/data",
"name": "${APPLICATION_NAME}-mysql-pvol"
}
],
"env": [
{
"name": "MYSQL_USER",
"value": "${DB_USERNAME}"
},
{
"name": "MYSQL_PASSWORD",
"value": "${DB_PASSWORD}"
},
{
"name": "MYSQL_DATABASE",
"value": "${DB_DATABASE}"
},
{
"name": "MYSQL_LOWER_CASE_TABLE_NAMES",
"value": "${MYSQL_LOWER_CASE_TABLE_NAMES}"
},
{
"name": "MYSQL_MAX_CONNECTIONS",
"value": "${MYSQL_MAX_CONNECTIONS}"
},
{
"name": "MYSQL_FT_MIN_WORD_LEN",
"value": "${MYSQL_FT_MIN_WORD_LEN}"
},
{
"name": "MYSQL_FT_MAX_WORD_LEN",
"value": "${MYSQL_FT_MAX_WORD_LEN}"
},
{
"name": "MYSQL_AIO",
"value": "${MYSQL_AIO}"
}
]
}
],
"volumes": [
{
"name": "${APPLICATION_NAME}-mysql-pvol",
"persistentVolumeClaim": {
"claimName": "${APPLICATION_NAME}-mysql-claim"
}
}
]
}
}
}
},
{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"name": "${APPLICATION_NAME}-mysql-claim",
"labels": {
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "${VOLUME_CAPACITY}"
}
}
}
}
],
"parameters": [
{
"name": "EAP_RELEASE",
"description": "EAP Release version, e.g. 6.4, etc.",
"value": "6.4"
},
{
"name": "APPLICATION_NAME",
"description": "The name for the application.",
"value": "eap-app"
},
{
"name": "APPLICATION_HOSTNAME",
"description": "Custom hostname for service routes. Leave blank for default hostname, e.g.: \u003capplication-name\u003e.\u003cproject\u003e.\u003cdefault-domain-suffix\u003e"
},
{
"name": "GIT_URI",
"description": "Git source URI for application"
},
{
"name": "GIT_REF",
"description": "Git branch/tag reference",
"value": "master"
},
{
"name": "GIT_CONTEXT_DIR",
"description": "Path within Git project to build; empty for root project directory."
},
{
"name": "DB_JNDI",
"description": "Database JNDI name used by application to resolve the datasource, e.g. java:/jboss/datasources/mysql"
},
{
"name": "DB_DATABASE",
"description": "Database name",
"value": "root"
},
{
"name": "VOLUME_CAPACITY",
"description": "Size of persistent storage for database volume.",
"value": "512Mi"
},
{
"name": "HORNETQ_QUEUES",
"description": "Queue names"
},
{
"name": "HORNETQ_TOPICS",
"description": "Topic names"
},
{
"name": "EAP_HTTPS_SECRET",
"description": "The name of the secret containing the keystore file",
"value": "eap-app-secret"
},
{
"name": "EAP_HTTPS_KEYSTORE",
"description": "The name of the keystore file within the secret",
"value": "keystore.jks"
},
{
"name": "EAP_HTTPS_NAME",
"description": "The name associated with the server certificate"
},
{
"name": "EAP_HTTPS_PASSWORD",
"description": "The password for the keystore and certificate"
},
{
"name": "DB_MIN_POOL_SIZE",
"description": "Sets xa-pool/min-pool-size for the configured datasource."
},
{
"name": "DB_MAX_POOL_SIZE",
"description": "Sets xa-pool/max-pool-size for the configured datasource."
},
{
"name": "DB_TX_ISOLATION",
"description": "Sets transaction-isolation for the configured datasource."
},
{
"name": "MYSQL_LOWER_CASE_TABLE_NAMES",
"description": "Sets how the table names are stored and compared."
},
{
"name": "MYSQL_MAX_CONNECTIONS",
"description": "The maximum permitted number of simultaneous client connections."
},
{
"name": "MYSQL_FT_MIN_WORD_LEN",
"description": "The minimum length of the word to be included in a FULLTEXT index."
},
{
"name": "MYSQL_FT_MAX_WORD_LEN",
"description": "The maximum length of the word to be included in a FULLTEXT index."
},
{
"name": "MYSQL_AIO",
"description": "Controls the innodb_use_native_aio setting value if the native AIO is broken."
},
{
"name": "HORNETQ_CLUSTER_PASSWORD",
"description": "HornetQ cluster admin password",
"generate": "expression",
"from": "[a-zA-Z0-9]{8}"
},
{
"name": "DB_USERNAME",
"description": "Database user name",
"generate": "expression",
"from": "user[a-zA-Z0-9]{3}"
},
{
"name": "DB_PASSWORD",
"description": "Database user password",
"generate": "expression",
"from": "[a-zA-Z0-9]{8}"
},
{
"name": "GITHUB_TRIGGER_SECRET",
"description": "Github trigger secret",
"generate": "expression",
"from": "[a-zA-Z0-9]{8}"
},
{
"name": "GENERIC_TRIGGER_SECRET",
"description": "Generic build trigger secret",
"generate": "expression",
"from": "[a-zA-Z0-9]{8}"
}
],
"labels": {
"template": "eap6-mysql-persistent-sti"
}
}
2.4. 为数据库提供持久化存储
(1)创建一个目录, 只有用户和组 nfsnobody 对其拥有全部权限:
[root@master ~]# mkdir -p /var/export/bookstoredbvol
[root@master ~]# chown nfsnobody:nfsnobody /var/export/bookstoredbvol
[root@master ~]# chmod 700 /var/export/bookstoredbvol
(2)export 该目录
[root@master ~]# vi /etc/exports
/var/export/bookstoredbvol *(rw,async,all_squash)
(3)允许客户端使用 NFS share:
[root@master ~]# exportfs -a
(4)复制 PV 定义文件到 root 用户主目录下, 并修改复制后的文件
[root@master ~]# cp /root/DO280/labs/lab-review/bookstoredb-volume.json /root/
"server": "master.pod0.example.com"
修改后的 bookstoredb-volume.json 的完整内容如下:
{
"apiVersion": "v1",
"kind": "PersistentVolume",
"metadata": {
"name": "bookstoredb-volume",
"labels": {
"application": "bookstore"
}
},
"spec": {
"capacity": {
"storage": "1Gi"
},
"accessModes": [ "ReadWriteOnce" ],
"nfs": {
"path": "/var/export/bookstoredbvol",
"server": "master.podX.example.com"
}
}
}
(5)注意 PV size 要和 template VOLUME_SIZE 参数相匹配:
"capacity": {
"storage": "1Gi"
},
(6)创建 PV:
[root@master ~]# oc create -f /root/bookstoredb-volume.json
2.5. 创建一个 secret 用于 application SSL certificate (全部在 workstation 主机)
(1)创建 secret:
[student@workstation ~]$ oc create -f /home/student/DO280/labs/lab-review/secret.json
说明: 手册中的 secret 定义文件使用的是 YAML 格式。
secret.json 完整内容如下:
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "ServiceAccount",
"apiVersion": "v1",
"metadata": {
"name": "eap-service-account"
},
"secrets": [
{
"name": "eap-app-secret-member"
}
]
},
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"annotations": {
"description": "Default secret file with name 'jboss' and password 'mykeystorepass'"
},
"name": "eap-app-secret-member"
},
"data": {
"keystore.jks": "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"
}
}
]
}
2.6. 根据导出的 template 创建 application (全部在 workstation 主机)
(1)为 oc process 命令提供参数
[student@workstation ~]$ vi /home/student/DO280/labs/lab-review/process-template.sh
#!/bin/bash
# do not add nor remove whitespace from the following command:
oc process -f eap6-mysql-persistent-sti.json -v \
APPLICATION_NAME=bookstore,\
APPLICATION_HOSTNAME=bookstore.cloudapps0.example.com,\
GIT_URI=http://workstation.pod0.example.com/bookstore,\
DB_JNDI=java:/jboss/datasources/mysql,\
DB_DATABASE=bookstoredb,\
DB_USERNAME=bookstoreapp,\
DB_PASSWORD=secret,\
EAP_HTTPS_SECRET=eap-app-secret-member,\
EAP_HTTPS_KEYSTORE=keystore.jks,\
EAP_HTTPS_NAME=jboss,\
EAP_HTTPS_PASSWORD=mykeystorepass,\
VOLUME_CAPACITY=1Gi \
> processed-template.json
[student@workstation ~]$ cp /home/student/DO280/labs/lab-review/process-template.sh .
(2)运行 oc process 命令产生资源定义文件
[student@workstation ~]$ bash process-template.sh
生成后的 processed-template.json 的完整内容如下:
{
"kind": "List",
"apiVersion": "v1beta3",
"metadata": {},
"items": [
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"description": "The web server's http port."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore"
},
"spec": {
"ports": [
{
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"deploymentConfig": "bookstore"
}
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"description": "The web server's https port."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "secure-bookstore"
},
"spec": {
"ports": [
{
"port": 8443,
"targetPort": 8443
}
],
"selector": {
"deploymentConfig": "bookstore"
}
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"description": "Ping service for clustered applications."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-ping"
},
"spec": {
"portalIP": "None",
"ports": [
{
"port": 8888,
"targetPort": 8888
}
],
"selector": {
"deploymentConfig": "bookstore"
}
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"description": "The database server's port."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-mysql"
},
"spec": {
"ports": [
{
"port": 3306,
"targetPort": 3306
}
],
"selector": {
"deploymentConfig": "bookstore-mysql"
}
}
},
{
"apiVersion": "v1",
"id": "bookstore-http-route",
"kind": "Route",
"metadata": {
"annotations": {
"description": "Route for application's http service."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-http-route"
},
"spec": {
"host": "bookstore.cloudapps0.example.com",
"to": {
"name": "bookstore"
}
}
},
{
"apiVersion": "v1",
"id": "bookstore-https-route",
"kind": "Route",
"metadata": {
"annotations": {
"description": "Route for application's https service."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-https-route"
},
"spec": {
"host": "bookstore.cloudapps0.example.com",
"tls": {
"termination": "passthrough"
},
"to": {
"name": "secure-bookstore"
}
}
},
{
"apiVersion": "v1",
"kind": "ImageStream",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore"
}
},
{
"apiVersion": "v1",
"kind": "BuildConfig",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore"
},
"spec": {
"output": {
"to": {
"kind": "ImageStreamTag",
"name": "bookstore:latest"
}
},
"source": {
"contextDir": "",
"git": {
"ref": "master",
"uri": "http://workstation.pod0.example.com/bookstore"
},
"type": "Git"
},
"strategy": {
"sourceStrategy": {
"from": {
"kind": "ImageStreamTag",
"name": "jboss-eap6-openshift:6.4",
"namespace": "openshift"
}
},
"type": "Source"
},
"triggers": [
{
"github": {
"secret": "xwrWajXC"
},
"type": "GitHub"
},
{
"generic": {
"secret": "doVsDd7R"
},
"type": "Generic"
},
{
"imageChange": {},
"type": "ImageChange"
}
]
}
},
{
"apiVersion": "v1",
"kind": "DeploymentConfig",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore"
},
"spec": {
"replicas": 1,
"selector": {
"deploymentConfig": "bookstore"
},
"strategy": {
"type": "Recreate"
},
"template": {
"metadata": {
"labels": {
"application": "bookstore",
"deploymentConfig": "bookstore"
},
"name": "bookstore"
},
"spec": {
"containers": [
{
"env": [
{
"name": "DB_SERVICE_PREFIX_MAPPING",
"value": "bookstore-mysql=DB"
},
{
"name": "DB_JNDI",
"value": "java:/jboss/datasources/mysql"
},
{
"name": "DB_USERNAME",
"value": "bookstoreapp"
},
{
"name": "DB_PASSWORD",
"value": "secret"
},
{
"name": "DB_DATABASE",
"value": "bookstoredb"
},
{
"name": "TX_DATABASE_PREFIX_MAPPING",
"value": "bookstore-mysql=DB"
},
{
"name": "DB_MIN_POOL_SIZE",
"value": ""
},
{
"name": "DB_MAX_POOL_SIZE",
"value": ""
},
{
"name": "DB_TX_ISOLATION",
"value": ""
},
{
"name": "OPENSHIFT_DNS_PING_SERVICE_NAME",
"value": "bookstore-ping"
},
{
"name": "OPENSHIFT_DNS_PING_SERVICE_PORT",
"value": "8888"
},
{
"name": "EAP_HTTPS_KEYSTORE_DIR",
"value": "/etc/eap-secret-volume"
},
{
"name": "EAP_HTTPS_KEYSTORE",
"value": "keystore.jks"
},
{
"name": "EAP_HTTPS_NAME",
"value": "jboss"
},
{
"name": "EAP_HTTPS_PASSWORD",
"value": "mykeystorepass"
},
{
"name": "HORNETQ_CLUSTER_PASSWORD",
"value": "CxVGPLVP"
},
{
"name": "HORNETQ_QUEUES",
"value": ""
},
{
"name": "HORNETQ_TOPICS",
"value": ""
}
],
"image": "bookstore",
"imagePullPolicy": "Always",
"name": "bookstore",
"ports": [
{
"containerPort": 8080,
"name": "http",
"protocol": "TCP"
},
{
"containerPort": 8443,
"name": "https",
"protocol": "TCP"
},
{
"containerPort": 8888,
"name": "ping",
"protocol": "TCP"
}
],
"readinessProbe": {
"exec": {
"command": [
"/bin/bash",
"-c",
"/opt/eap/bin/readinessProbe.sh"
]
}
},
"volumeMounts": [
{
"mountPath": "/etc/eap-secret-volume",
"name": "eap-keystore-volume",
"readOnly": true
}
]
}
],
"serviceAccount": "eap-service-account",
"volumes": [
{
"name": "eap-keystore-volume",
"secret": {
"secretName": "eap-app-secret-member"
}
}
]
}
},
"triggers": [
{
"imageChangeParams": {
"automatic": true,
"containerNames": [
"bookstore"
],
"from": {
"kind": "ImageStream",
"name": "bookstore"
}
},
"type": "ImageChange"
}
]
}
},
{
"apiVersion": "v1",
"kind": "DeploymentConfig",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-mysql"
},
"spec": {
"replicas": 1,
"selector": {
"deploymentConfig": "bookstore-mysql"
},
"strategy": {
"type": "Recreate"
},
"template": {
"metadata": {
"labels": {
"application": "bookstore",
"deploymentConfig": "bookstore-mysql"
},
"name": "bookstore-mysql"
},
"spec": {
"containers": [
{
"env": [
{
"name": "MYSQL_USER",
"value": "bookstoreapp"
},
{
"name": "MYSQL_PASSWORD",
"value": "secret"
},
{
"name": "MYSQL_DATABASE",
"value": "bookstoredb"
},
{
"name": "MYSQL_LOWER_CASE_TABLE_NAMES",
"value": ""
},
{
"name": "MYSQL_MAX_CONNECTIONS",
"value": ""
},
{
"name": "MYSQL_FT_MIN_WORD_LEN",
"value": ""
},
{
"name": "MYSQL_FT_MAX_WORD_LEN",
"value": ""
},
{
"name": "MYSQL_AIO",
"value": ""
}
],
"image": "mysql",
"imagePullPolicy": "Always",
"name": "bookstore-mysql",
"ports": [
{
"containerPort": 3306,
"protocol": "TCP"
}
],
"volumeMounts": [
{
"mountPath": "/var/lib/mysql/data",
"name": "bookstore-mysql-pvol"
}
]
}
],
"volumes": [
{
"name": "bookstore-mysql-pvol",
"persistentVolumeClaim": {
"claimName": "bookstore-mysql-claim"
}
}
]
}
},
"triggers": [
{
"imageChangeParams": {
"automatic": true,
"containerNames": [
"bookstore-mysql"
],
"from": {
"kind": "ImageStreamTag",
"name": "mysql:latest",
"namespace": "openshift"
}
},
"type": "ImageChange"
}
]
}
},
{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-mysql-claim"
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "1Gi"
}
}
}
}
]
}
(3)发布 application
[student@workstation ~]$ oc create -f processed-template.json
2.7. 等待直到 application build 并且运行,这一步等待时间较长,请耐心
(1)确认 build 启动
[student@workstation ~]$ oc get builds
(2)查看 build 日志:
[student@workstation ~]$ oc build-logs bookstore-1
(3)确认 application 和 database pods 启动:
[student@workstation ~]$ oc get pods
注意: REASON ExitCode:0 表示 build 成功。
2.8. 确认 application 没有启动成功, 因为数据库没有数据
(1)查看 application pod 日志
[student@workstation ~]$ oc logs bookstore-1-m6ynh | tail -n 6
[student@workstation ~]$ oc logs bookstore-1-m6ynh | less
2.9. 为数据库增加数据
(1)转发本地端口到 database pod:
[student@workstation ~]$ oc port-forward -p bookstore-mysql-1-28zyg 13306:3306
(2)新开一个终端, 安装 MySQL client:
[student@workstation ~]$ sudo yum -y install mysql
(3)git 克隆, 获取 SQL script:
[student@workstation ~]$ git clone http://workstation.pod0.example.com/bookstore
(4)运行 SQL script
[student@workstation ~]$ mysql -h127.0.0.1 -ubookstoreapp -psecret -P13306 bookstoredb < bookstore/sql/bookstore.sql
(5)确认 database volume 包含有所有 tables
[root@master ~]# ls /var/export/bookstoredbvol/bookstoredb/
(6)停止本地端口转发
Ctrl + C 终止另一个终端运行的 oc port-forward 进程。
2.10. 强制 OSE 创建一个新的 application pod, 并确认启动成功
(1)删除原来失败的 application pod:
[student@workstation ~]$ oc delete pod bookstore-1-m6ynh
(2)确认一个新的 pod 生成, 并等待其启动成功
[student@workstation ~]$ oc get pod
(3)查看 application pod 日志, 确认连接数据库成功
[student@workstation ~]$ oc logs bookstore-1-wp81p | tail -n 5
3. 访问 Bookstore Application
3.1. 确认 application route 到正确的主机
(1)template 参数 APPLICATION_URL
[student@workstation ~]$ oc describe route bookstore
(2)如果 route host 属性不正确, 可以使用 oc edit 修改
3.2. 访问 application
打开浏览器, 访问 bookstore.cloudapps0.example.com
0. 开始实验之前, 重置所有虚机,重置后会自动重新启动所有虚机
[kiosk@fundation0 ~]$ rht-vmctl reset all
1. 安装 OSE 3.0
1.1 OSE 3.0 安装先决条件
(1)确认 master 节点主机已经注册了必须的软件频道(node 节点主机也做此步)
[root@master ~]# yum repolist
(2)安装必要软件,一共 9 个软件(node 节点主机也做此步)
[root@master ~]# yum -y install docker wget git net-tools bind-utils iptables-services bridge-utils python-virtualenv gcc
(3)确认主机名和 IP 地址对应(node 节点主机也做此步)
[root@master ~]# host $(hostname -f)(node 节点主机也做此步)
(4)生成 SSH 无密码的公钥和私钥对
[root@master ~]# ssh-keygen -N ''
(5)复制 SSH 公钥到所有主机
[root@master ~]# ssh-copy-id root@node.pod0.example.com 口令 redhat
[root@master ~]# ssh-copy-id root@master.pod0.example.com 口令 redhat
(6)stop 并 disable NetworkManager 和 firewalld(node 节点主机也做此步)
[root@master ~]# systemctl stop NetworkManager
[root@master ~]# systemctl disable NetworkManager
[root@master ~]# systemctl stop firewalld
[root@master ~]# systemctl disable firewalld
1.2. 配置 docker daemon
(1)安装 private registry 证书作为受信证书(node 节点主机也做此步)
[root@master ~]# yum -y install ca-certificates
[root@master ~]# update-ca-trust enable
[root@master ~]# scp root@workstation.pod0.example.com:/etc/pki/tls/certs/self.crt /etc/pki/ca-trust/source/anchors/
[root@master ~]# update-ca-trust extract
(2)在继续下一步之前, 确认停止 docker(node 节点主机也做此步)
[root@master ~]# systemctl stop docker
(3)修改文件, 确认只搜索 private registry(node 节点主机也做此步)
[root@master ~]# vi /etc/sysconfig/docker
#ADD_REGISTRY='--add-registry registry.access.redhat.com'
ADD_REGISTRY='--add-registry workstation.pod0.example.com:5000'
BLOCK_REGISTRY='--block-registry public --block-registry registry.access.redhat.com'
(4)创建新文件, 指定容器(非持久存储)使用 LVM thinpool(node 节点主机也做此步)
[root@master ~]# vi /etc/sysconfig/docker-storage-setup
DEVS=/dev/vdb
VG=docker-vg
SETUP_LVM_THIN_POOL=yes
(5)配置 LVM thinpool(node 节点主机也做此步)
[root@master ~]# lvmconf --disable-cluster
[root@master ~]# docker-storage-setup
(6)再次 start 并 enable docker(node 节点主机也做此步)
[root@master ~]# systemctl start docker
[root@master ~]# systemctl enable docker
1.3. 预取所有 OSE 以及运行时容器 images 到所有主机
(1)用脚本 pull 所有 images (node 节点主机也做此步)
[root@master ~]# /root/DO280/labs/lab-review/fetch.sh
fetch.sh 脚本内容如下:
#!/bin/bash
# OSE 3 containerized services images
# Needs version because the private repo do not have ":latest" tags
for image in \
openshift3/ose-haproxy-router openshift3/ose-deployer openshift3/ose-sti-builder openshift3/ose-sti-image-builder \
penshift3/ose-docker-builder openshift3/ose-pod openshift3/ose-docker-registry openshift3/ose-keepalived-ipfailover
do docker pull $image:v3.0.1.0; done
# OSE 3 runtime images
for image in \
openshift3/ruby-20-rhel7 openshift3/php-55-rhel7 openshift3/nodejs-010-rhel7 openshift3/mysql-55-rhel7 \
jboss-eap-6/eap-openshift
do docker pull $image; done
# sample images
for image in \
openshift/hello-openshift php-quote
do docker pull $image; done
重要说明:
(1)如果没有脚本, 搜索 openshift3, 然后再 pull 具体的 image (node 节点主机也做此步)
[root@master ~]# docker search openshift3
[root@master ~]# docker pull openshift3/ose-haproxy-router
(2)某些 images, 比如 xPaaS images 没有 openshift3 作为名字的一部分。
作为本实验, 记得下载 jboss-eap-6/eap-openshift image。
(3)不要搜索 openshift, 然后下载所有返回的 images, 因为大多数 images 来自社区, 没有经过认证。
[root@master ~]# docker search openshift
1.4. 运行 OSE 快速安装脚本
(1)解压
[root@master ~]# mkdir ose-installer ; cd ose-installer
[root@master ose-installer]# tar xzf /root/DO280/installers/oo-install-ose.tgz
(2)安装
[root@master ose-installer]# ./oo-install-ose
• 输入 Y 确认继续
• 回车确认 root 作为 ssh 访问用户
• 按任意键继续, 准备添加 master 主机名列表
• 安装程序会打开一个 vi 编辑器, 输入 master 主机名列表:
master.pod0.example.com
wq!保存
• 输入 Y 确认 master 主机名列表
• 按任意键继续, 准备添加 node 主机名列表, 注意 master 也是一种 node
• 安装程序会打开一个 vi 编辑器, 输入 node 主机名列表: (注意 master 也是一种 node, 并且已经添加了 master)
• 输入 node 主机名列表:
master.pod0.example.com // 已添加
node.pod0.example.com
wq!保存
• 输入 Y 确认 node 主机名列表
• 按任意键继续
• 安装程序会打开一个 vi 编辑器, 包含所有的 master 和 node 主机名和 IP 地址列表
确认无误后, wq!保存
• 输入 Y 确认继续
• 出现 The installation was successful!信息后, 按任意键继续
• 确认信息正确
• 如果一切正确, 输入 Y 开始安装
(3)安装完毕后, 检查主机状态
[root@master ~]# oc get nodes
(4)确认 openshift services 都正常启动了
[root@master ~]# systemctl status openshift-master
[root@master ~]# systemctl status openshift-node
[root@node ~]# systemctl status openshift-node
1.5. 修改 OSE image streams
S2I 时, 会从 registry pull images, 默认指向的地址是 redhat private registry, 需要修改成实验环境下的 registry。
[root@master ~]# oc edit is -n openshift
会打开一个 vi 编辑器, 执行如下替换
:%s/registry.access.redhat.com/workstation.pod0.example.com:5000
1.6. 使用 Apache htpasswd 作为 OSE 的认证方式
(1)安装 httpd-tools package
[root@master ~]# yum -y install httpd-tools
(2)修改 /etc/openshift/master/master-config.yaml
找到 oauthConfig 部分
增加一个 file 属性 /etc/openshift/openshift-passwd
kind 属性 替换 DenyAllPasswordIdentityProvider 为 HTPasswdPasswordIdentityProvider
(3)创建 /etc/openshift/openshift-passwd 文件
[root@master ~]# touch /etc/openshift/openshift-passwd
(4)重启 openshift-master
[root@master ~]# systemctl restart openshift-master
1.7. 发布 OSE router 和 internal registry
(1)配置 OSE master 使用正确的 DNS wild-card domain 名称
[root@master ~]# vi /etc/openshift/master/master-config.yaml
routingConfig
subdomain: cloudapps0.example.com
[root@master ~]# systemctl restart openshift-master
(2)创建 router service account
[root@master ~]# echo '{"kind":"ServiceAccount","apiVersion":"v1","metadata":{"name":"router"}}' | oc create -f -
(3)修改 privileged security context constraints (SCC), 加入 router service account
[root@master ~]# oc edit scc privileged
找到 users:,在其下面增加一个新用户 system:serviceaccount:default:router :
users:
- system:serviceaccount:default:router
- system:serviceaccount:openshift-infra:build-controller
注意:可以运行脚本 /root/DO280/labs/lab-review/router_scc.sh 创建 service account 并且加到 privileged SCC。
router_scc.sh 脚本内容如下:
#!/bin/bash
echo \
'{"kind":"ServiceAccount","apiVersion":"v1","metadata":{"name":"router"}}' \
| oc create -f -
oc get scc privileged -o yaml > scc_privileged.yaml
sed -i '
/users:/ a \
- system:serviceaccount:default:router
' scc_privileged.yaml
oc replace scc privileged -f scc_privileged.yaml
(4)发布默认的 HAProxy router
[root@master ~]# oadm router oserouter --credentials='/etc/openshift/master/openshift-router.kubeconfig' --images='openshift3/ose-haproxy-router:${version}' --service-account=router
确认 router pod 运行起来后, 再执行下一步
[root@master ~]# oc get pods
(5)发布 OSE internal container image registry
[root@master ~]# oadm registry --credentials=/etc/openshift/master/openshift-registry.kubeconfig --images='openshift3/ose-docker-registry:${version}'
确认 registry pod 运行起来后, 再执行下一步
[root@master ~]# oc get pods
1.8. 为 OSE internal registry 提供持久化存储
(1)安装并配置 NFS Server(master)和 NFS Client(node)
[root@master ~]# bash /root/DO280/labs/lab-review/config-nfs-server.sh
config-nfs-server.sh 脚本内容如下:
#!/bin/bash
# OSE 3.0.1.0 packages already add nfs-utils as dependency
#yum -y install nfs-utils
#ssh root@node yum -y install nfs-utils
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 111 -j ACCEPT
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2049 -j ACCEPT
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 20048 -j ACCEPT
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 50825 -j ACCEPT
iptables -I OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 53248 -j ACCEPT
sed -i '/COMMIT/ i \
# BEGIN NFS server \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 53248 -j ACCEPT \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 50825 -j ACCEPT \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 20048 -j ACCEPT \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 2049 -j ACCEPT \
-A OS_FIREWALL_ALLOW -p tcp -m state --state NEW -m tcp --dport 111 -j ACCEPT \
# END NFS server' /etc/sysconfig/iptables
# DO NOT restart iptables. Restarting it looses rules added by docker and openshift-sdn
sed -i '
s/RPCMOUNTDOPTS=""/RPCMOUNTDOPTS="-p 20048"/
s/STATDARG=""/STATDARG="-p 50825"/
' /etc/sysconfig/nfs
echo '
fs.nfs.nlm_tcpport=53248
fs.nfs.nlm_udpport=53248
' >> /etc/sysctl.conf
modprobe nfsd
sysctl -p
for u in rpcbind nfs-server nfs-lock nfs-idmap; do
systemctl enable $u
systemctl start $u
done
setsebool -P virt_use_nfs=true
ssh root@node setsebool -P virt_use_nfs=true
(2)发布 OSE internal container image registry
[root@master ~]# mkdir -p /var/export/registryvol
[root@master ~]# chown nfsnobody:nfsnobody /var/export/registryvol
[root@master ~]# chmod 700 /var/export/registryvol
(3)Export 该目录
[root@master ~]# vi /etc/exports
增加一行内容如下:
/var/export/registryvol *(rw,async,all_squash)
(4)允许客户端访问
[root@master ~]# exportfs -a
(5)复制 PV 定义文件
[root@master ~]# cp /root/DO280/labs/lab-review/registry-volume.json /root
[root@master ~]# vi /root/registry-volume.json
修改内容如下:
"server": "master.pod0.example.com"
修改后的 registry-volume.json 的完整内容如下:
{
"apiVersion": "v1",
"kind": "PersistentVolume",
"metadata": {
"name": "registry-volume",
"labels": {
"deploymentconfig": "docker-registry"
}
},
"spec": {
"capacity": {
"storage": "10Gi"
},
"accessModes": [ "ReadWriteMany" ],
"nfs": {
"path": "/var/export/registryvol",
"server": "master.pod0.example.com"
}
}
}
说明: OpenShift Enterprise Developer Guide 有 YAML 格式的 PV 定义。
(6)创建 PV
[root@master ~]# oc create -f /root/registry-volume.json
1.9. 绑定 PV 到 registry pod
(1)创建 PVClaim
[root@master ~]# oc create -f /root/DO280/labs/lab-review/registry-pvclaim.json
registry-pvclaim.json 的完整内容如下:
{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"name": "registry-pvclaim",
"labels": {
"deploymentconfig": "docker-registry"
}
},
"spec": {
"accessModes": [ "ReadWriteMany" ],
"resources": {
"requests": {
"storage": "10Gi"
}
}
}
}
(2)确认 PVClaim 绑定到了 PV
[root@master ~]# oc get pvc
(3)修改 DeploymentConfig docker-registry to use the PVClaim:
[root@master ~]# oc volume dc docker-registry --add --overwrite -t persistentVolumeClaim --claim-name=registry-pvclaim --name=registry-storage
(4)修改 docker-registry dc 后,确认 DeploymentConfig docker-registry 启动了一个新的 registry pod
[root@master ~]# oc status
(5)确认 registry 工作正常
[root@master ~]# oc describe service docker-registry
(6)访问 registry API,确认 registry pod 工作正常
[root@master ~]# curl http://172.30.10.176:5000/healthz
2. 发布 Bookstore 应用
2.1. 创建用户 developer
(1)使用 htpasswd 创建用户
[root@master ~]# htpasswd -b /etc/openshift/openshift-passwd developer openshift
2.2. 创建 project 并增加 quota 限制
(1)安装 OSE client (workstation 主机)
[student@workstation ~]$ sudo yum -y install openshift
输入口令 student
(2)以 developer 账户登录 (workstation 主机)
[student@workstation ~]$ oc login -u developer -p openshift
由于是第一次登录,会询问 master 的信息, 输入 https://master.pod0.example.com:8443
并使用 insecure connections? (y/n): y
(3)创建 project bookstore (workstation 主机)
[student@workstation ~]$ oc new-project bookstore
(4)为 project bookstore 增加限制 quota (master 主机)
[root@master ~]# oc create -f /root/DO280/labs/lab-review/project-quotas.json -n bookstore
project-quotas.json 的完整内容如下:
{
"apiVersion": "v1",
"kind": "ResourceQuota",
"metadata": {
"name": "bookstore-project-quotas"
},
"spec": {
"hard": {
"memory": "16Gi",
"cpu": "6000m",
"pods": "6",
"services": "8",
"replicationcontrollers": "5",
"persistentvolumeclaims": "2"
}
}
}
(5)为 project bookstore 增加限制 limit (master 主机)
[root@master ~]# oc create -f /root/DO280/labs/lab-review/project-limits.json -n bookstore
project-limits.json 的完整内容如下:
{
"kind": "LimitRange",
"apiVersion": "v1",
"metadata": {
"name": "bookstore-project-limits"
},
"spec": {
"limits": [
{
"type": "Pod",
"max": {
"cpu": "500m",
"memory": "4Gi"
},
"min": {
"cpu": "200m",
"memory": "512Mi"
}
},
{
"type": "Container",
"max": {
"cpu": "500m",
"memory": "4Gi"
},
"min": {
"cpu": "200m",
"memory": "512Mi"
},
"default": {
"cpu": "200m",
"memory": "1.5Gi"
}
}
]
}
}
2.3. 查看并确认 application template 的参数 (全部在 workstation 主机)
(1)列出 template eap6-mysql-persistent-sti 的所有参数
[student@workstation ~]$ oc process --parameters eap6-mysql-persistent-sti -n openshift | sort
输出如下:
DB_DATABASE Database name
DB_USERNAME Database user name
DB_PASSWORD Database user password
EAP_HTTPS_SECRET The name of the secret containing the keystore file
EAP_HTTPS_KEYSTORE The name of the keystore file within the secret
EAP_HTTPS_NAME The name associated with the server certificate
EAP_HTTPS_PASSWORD The password for the keystore and certificate
GIT_URI Git source URI for application
VOLUME_CAPACITY Size of persistent storage for database volume
(2)导出 application template
[student@workstation ~]$ oc export template eap6-mysql-persistent-sti -o json -n openshift > eap6-mysql-persistent-sti.json
(3)分析导出的 template 文件 eap6-mysql-persistent-sti.json
[student@workstation ~]$ vim eap6-mysql-persistent-sti.json
检查如下参数配置:
◦ 2 个 pods: 一个是 application pod,一个是 database pod, 分别在各自的 DeploymentConfig 中配置。
◦ 1 个 BuildConfig:用来从 source code 生成 application image。
◦ 1 个 ImageStream:用来生成 application image。
◦ 2 个 services:一个是 application,一个是 database。
◦ 1 个额外的 service:用做 JBoss EAP clustering。
◦ 2 个 routes:全都是为了 application pod service,一个用 HTTP,一个用 HTTPS。
◦ 1 个 PVClaim:用做 database data volume。
eap6-mysql-persistent-sti.json 完整内容如下:
{
"kind": "Template",
"apiVersion": "v1",
"metadata": {
"name": "eap6-mysql-persistent-sti",
"creationTimestamp": null,
"annotations": {
"description": "Application template for EAP 6 MySQL applications with persistent storage built using STI.",
"iconClass": "icon-jboss"
}
},
"objects": [
{
"kind": "Service",
"apiVersion": "v1",
"spec": {
"ports": [
{
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"deploymentConfig": "${APPLICATION_NAME}"
}
},
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "The web server's http port."
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"spec": {
"ports": [
{
"port": 8443,
"targetPort": 8443
}
],
"selector": {
"deploymentConfig": "${APPLICATION_NAME}"
}
},
"metadata": {
"name": "secure-${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "The web server's https port."
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"spec": {
"ports": [
{
"port": 8888,
"targetPort": 8888
}
],
"portalIP": "None",
"selector": {
"deploymentConfig": "${APPLICATION_NAME}"
}
},
"metadata": {
"name": "${APPLICATION_NAME}-ping",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "Ping service for clustered applications."
}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"spec": {
"ports": [
{
"port": 3306,
"targetPort": 3306
}
],
"selector": {
"deploymentConfig": "${APPLICATION_NAME}-mysql"
}
},
"metadata": {
"name": "${APPLICATION_NAME}-mysql",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "The database server's port."
}
}
},
{
"kind": "Route",
"apiVersion": "v1",
"id": "${APPLICATION_NAME}-http-route",
"metadata": {
"name": "${APPLICATION_NAME}-http-route",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "Route for application's http service."
}
},
"spec": {
"host": "${APPLICATION_HOSTNAME}",
"to": {
"name": "${APPLICATION_NAME}"
}
}
},
{
"kind": "Route",
"apiVersion": "v1",
"id": "${APPLICATION_NAME}-https-route",
"metadata": {
"name": "${APPLICATION_NAME}-https-route",
"labels": {
"application": "${APPLICATION_NAME}"
},
"annotations": {
"description": "Route for application's https service."
}
},
"spec": {
"host": "${APPLICATION_HOSTNAME}",
"to": {
"name": "secure-${APPLICATION_NAME}"
},
"tls": {
"termination": "passthrough"
}
}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
}
}
},
{
"kind": "BuildConfig",
"apiVersion": "v1",
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"source": {
"type": "Git",
"git": {
"uri": "${GIT_URI}",
"ref": "${GIT_REF}"
},
"contextDir": "${GIT_CONTEXT_DIR}"
},
"strategy": {
"type": "Source",
"sourceStrategy": {
"from": {
"kind": "ImageStreamTag",
"namespace": "openshift",
"name": "jboss-eap6-openshift:${EAP_RELEASE}"
}
}
},
"output": {
"to": {
"kind": "ImageStreamTag",
"name": "${APPLICATION_NAME}:latest"
}
},
"triggers": [
{
"type": "GitHub",
"github": {
"secret": "${GITHUB_TRIGGER_SECRET}"
}
},
{
"type": "Generic",
"generic": {
"secret": "${GENERIC_TRIGGER_SECRET}"
}
},
{
"type": "ImageChange",
"imageChange": {}
}
]
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"strategy": {
"type": "Recreate"
},
"triggers": [
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"${APPLICATION_NAME}"
],
"from": {
"kind": "ImageStream",
"name": "${APPLICATION_NAME}"
}
}
}
],
"replicas": 1,
"selector": {
"deploymentConfig": "${APPLICATION_NAME}"
},
"template": {
"metadata": {
"name": "${APPLICATION_NAME}",
"labels": {
"deploymentConfig": "${APPLICATION_NAME}",
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"serviceAccount": "eap-service-account",
"containers": [
{
"name": "${APPLICATION_NAME}",
"image": "${APPLICATION_NAME}",
"imagePullPolicy": "Always",
"volumeMounts": [
{
"name": "eap-keystore-volume",
"mountPath": "/etc/eap-secret-volume",
"readOnly": true
}
],
"readinessProbe": {
"exec": {
"command": [
"/bin/bash",
"-c",
"/opt/eap/bin/readinessProbe.sh"
]
}
},
"ports": [
{
"name": "http",
"containerPort": 8080,
"protocol": "TCP"
},
{
"name": "https",
"containerPort": 8443,
"protocol": "TCP"
},
{
"name": "ping",
"containerPort": 8888,
"protocol": "TCP"
}
],
"env": [
{
"name": "DB_SERVICE_PREFIX_MAPPING",
"value": "${APPLICATION_NAME}-mysql=DB"
},
{
"name": "DB_JNDI",
"value": "${DB_JNDI}"
},
{
"name": "DB_USERNAME",
"value": "${DB_USERNAME}"
},
{
"name": "DB_PASSWORD",
"value": "${DB_PASSWORD}"
},
{
"name": "DB_DATABASE",
"value": "${DB_DATABASE}"
},
{
"name": "TX_DATABASE_PREFIX_MAPPING",
"value": "${APPLICATION_NAME}-mysql=DB"
},
{
"name": "DB_MIN_POOL_SIZE",
"value": "${DB_MIN_POOL_SIZE}"
},
{
"name": "DB_MAX_POOL_SIZE",
"value": "${DB_MAX_POOL_SIZE}"
},
{
"name": "DB_TX_ISOLATION",
"value": "${DB_TX_ISOLATION}"
},
{
"name": "OPENSHIFT_DNS_PING_SERVICE_NAME",
"value": "${APPLICATION_NAME}-ping"
},
{
"name": "OPENSHIFT_DNS_PING_SERVICE_PORT",
"value": "8888"
},
{
"name": "EAP_HTTPS_KEYSTORE_DIR",
"value": "/etc/eap-secret-volume"
},
{
"name": "EAP_HTTPS_KEYSTORE",
"value": "${EAP_HTTPS_KEYSTORE}"
},
{
"name": "EAP_HTTPS_NAME",
"value": "${EAP_HTTPS_NAME}"
},
{
"name": "EAP_HTTPS_PASSWORD",
"value": "${EAP_HTTPS_PASSWORD}"
},
{
"name": "HORNETQ_CLUSTER_PASSWORD",
"value": "${HORNETQ_CLUSTER_PASSWORD}"
},
{
"name": "HORNETQ_QUEUES",
"value": "${HORNETQ_QUEUES}"
},
{
"name": "HORNETQ_TOPICS",
"value": "${HORNETQ_TOPICS}"
}
]
}
],
"volumes": [
{
"name": "eap-keystore-volume",
"secret": {
"secretName": "${EAP_HTTPS_SECRET}"
}
}
]
}
}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "${APPLICATION_NAME}-mysql",
"labels": {
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"strategy": {
"type": "Recreate"
},
"triggers": [
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"${APPLICATION_NAME}-mysql"
],
"from": {
"kind": "ImageStreamTag",
"namespace": "openshift",
"name": "mysql:latest"
}
}
}
],
"replicas": 1,
"selector": {
"deploymentConfig": "${APPLICATION_NAME}-mysql"
},
"template": {
"metadata": {
"name": "${APPLICATION_NAME}-mysql",
"labels": {
"deploymentConfig": "${APPLICATION_NAME}-mysql",
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"containers": [
{
"name": "${APPLICATION_NAME}-mysql",
"image": "mysql",
"imagePullPolicy": "Always",
"ports": [
{
"containerPort": 3306,
"protocol": "TCP"
}
],
"volumeMounts": [
{
"mountPath": "/var/lib/mysql/data",
"name": "${APPLICATION_NAME}-mysql-pvol"
}
],
"env": [
{
"name": "MYSQL_USER",
"value": "${DB_USERNAME}"
},
{
"name": "MYSQL_PASSWORD",
"value": "${DB_PASSWORD}"
},
{
"name": "MYSQL_DATABASE",
"value": "${DB_DATABASE}"
},
{
"name": "MYSQL_LOWER_CASE_TABLE_NAMES",
"value": "${MYSQL_LOWER_CASE_TABLE_NAMES}"
},
{
"name": "MYSQL_MAX_CONNECTIONS",
"value": "${MYSQL_MAX_CONNECTIONS}"
},
{
"name": "MYSQL_FT_MIN_WORD_LEN",
"value": "${MYSQL_FT_MIN_WORD_LEN}"
},
{
"name": "MYSQL_FT_MAX_WORD_LEN",
"value": "${MYSQL_FT_MAX_WORD_LEN}"
},
{
"name": "MYSQL_AIO",
"value": "${MYSQL_AIO}"
}
]
}
],
"volumes": [
{
"name": "${APPLICATION_NAME}-mysql-pvol",
"persistentVolumeClaim": {
"claimName": "${APPLICATION_NAME}-mysql-claim"
}
}
]
}
}
}
},
{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"name": "${APPLICATION_NAME}-mysql-claim",
"labels": {
"application": "${APPLICATION_NAME}"
}
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "${VOLUME_CAPACITY}"
}
}
}
}
],
"parameters": [
{
"name": "EAP_RELEASE",
"description": "EAP Release version, e.g. 6.4, etc.",
"value": "6.4"
},
{
"name": "APPLICATION_NAME",
"description": "The name for the application.",
"value": "eap-app"
},
{
"name": "APPLICATION_HOSTNAME",
"description": "Custom hostname for service routes. Leave blank for default hostname, e.g.: \u003capplication-name\u003e.\u003cproject\u003e.\u003cdefault-domain-suffix\u003e"
},
{
"name": "GIT_URI",
"description": "Git source URI for application"
},
{
"name": "GIT_REF",
"description": "Git branch/tag reference",
"value": "master"
},
{
"name": "GIT_CONTEXT_DIR",
"description": "Path within Git project to build; empty for root project directory."
},
{
"name": "DB_JNDI",
"description": "Database JNDI name used by application to resolve the datasource, e.g. java:/jboss/datasources/mysql"
},
{
"name": "DB_DATABASE",
"description": "Database name",
"value": "root"
},
{
"name": "VOLUME_CAPACITY",
"description": "Size of persistent storage for database volume.",
"value": "512Mi"
},
{
"name": "HORNETQ_QUEUES",
"description": "Queue names"
},
{
"name": "HORNETQ_TOPICS",
"description": "Topic names"
},
{
"name": "EAP_HTTPS_SECRET",
"description": "The name of the secret containing the keystore file",
"value": "eap-app-secret"
},
{
"name": "EAP_HTTPS_KEYSTORE",
"description": "The name of the keystore file within the secret",
"value": "keystore.jks"
},
{
"name": "EAP_HTTPS_NAME",
"description": "The name associated with the server certificate"
},
{
"name": "EAP_HTTPS_PASSWORD",
"description": "The password for the keystore and certificate"
},
{
"name": "DB_MIN_POOL_SIZE",
"description": "Sets xa-pool/min-pool-size for the configured datasource."
},
{
"name": "DB_MAX_POOL_SIZE",
"description": "Sets xa-pool/max-pool-size for the configured datasource."
},
{
"name": "DB_TX_ISOLATION",
"description": "Sets transaction-isolation for the configured datasource."
},
{
"name": "MYSQL_LOWER_CASE_TABLE_NAMES",
"description": "Sets how the table names are stored and compared."
},
{
"name": "MYSQL_MAX_CONNECTIONS",
"description": "The maximum permitted number of simultaneous client connections."
},
{
"name": "MYSQL_FT_MIN_WORD_LEN",
"description": "The minimum length of the word to be included in a FULLTEXT index."
},
{
"name": "MYSQL_FT_MAX_WORD_LEN",
"description": "The maximum length of the word to be included in a FULLTEXT index."
},
{
"name": "MYSQL_AIO",
"description": "Controls the innodb_use_native_aio setting value if the native AIO is broken."
},
{
"name": "HORNETQ_CLUSTER_PASSWORD",
"description": "HornetQ cluster admin password",
"generate": "expression",
"from": "[a-zA-Z0-9]{8}"
},
{
"name": "DB_USERNAME",
"description": "Database user name",
"generate": "expression",
"from": "user[a-zA-Z0-9]{3}"
},
{
"name": "DB_PASSWORD",
"description": "Database user password",
"generate": "expression",
"from": "[a-zA-Z0-9]{8}"
},
{
"name": "GITHUB_TRIGGER_SECRET",
"description": "Github trigger secret",
"generate": "expression",
"from": "[a-zA-Z0-9]{8}"
},
{
"name": "GENERIC_TRIGGER_SECRET",
"description": "Generic build trigger secret",
"generate": "expression",
"from": "[a-zA-Z0-9]{8}"
}
],
"labels": {
"template": "eap6-mysql-persistent-sti"
}
}
2.4. 为数据库提供持久化存储
(1)创建一个目录, 只有用户和组 nfsnobody 对其拥有全部权限:
[root@master ~]# mkdir -p /var/export/bookstoredbvol
[root@master ~]# chown nfsnobody:nfsnobody /var/export/bookstoredbvol
[root@master ~]# chmod 700 /var/export/bookstoredbvol
(2)export 该目录
[root@master ~]# vi /etc/exports
/var/export/bookstoredbvol *(rw,async,all_squash)
(3)允许客户端使用 NFS share:
[root@master ~]# exportfs -a
(4)复制 PV 定义文件到 root 用户主目录下, 并修改复制后的文件
[root@master ~]# cp /root/DO280/labs/lab-review/bookstoredb-volume.json /root/
"server": "master.pod0.example.com"
修改后的 bookstoredb-volume.json 的完整内容如下:
{
"apiVersion": "v1",
"kind": "PersistentVolume",
"metadata": {
"name": "bookstoredb-volume",
"labels": {
"application": "bookstore"
}
},
"spec": {
"capacity": {
"storage": "1Gi"
},
"accessModes": [ "ReadWriteOnce" ],
"nfs": {
"path": "/var/export/bookstoredbvol",
"server": "master.podX.example.com"
}
}
}
(5)注意 PV size 要和 template VOLUME_SIZE 参数相匹配:
"capacity": {
"storage": "1Gi"
},
(6)创建 PV:
[root@master ~]# oc create -f /root/bookstoredb-volume.json
2.5. 创建一个 secret 用于 application SSL certificate (全部在 workstation 主机)
(1)创建 secret:
[student@workstation ~]$ oc create -f /home/student/DO280/labs/lab-review/secret.json
说明: 手册中的 secret 定义文件使用的是 YAML 格式。
secret.json 完整内容如下:
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "ServiceAccount",
"apiVersion": "v1",
"metadata": {
"name": "eap-service-account"
},
"secrets": [
{
"name": "eap-app-secret-member"
}
]
},
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"annotations": {
"description": "Default secret file with name 'jboss' and password 'mykeystorepass'"
},
"name": "eap-app-secret-member"
},
"data": {
"keystore.jks": "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"
}
}
]
}
2.6. 根据导出的 template 创建 application (全部在 workstation 主机)
(1)为 oc process 命令提供参数
[student@workstation ~]$ vi /home/student/DO280/labs/lab-review/process-template.sh
#!/bin/bash
# do not add nor remove whitespace from the following command:
oc process -f eap6-mysql-persistent-sti.json -v \
APPLICATION_NAME=bookstore,\
APPLICATION_HOSTNAME=bookstore.cloudapps0.example.com,\
GIT_URI=http://workstation.pod0.example.com/bookstore,\
DB_JNDI=java:/jboss/datasources/mysql,\
DB_DATABASE=bookstoredb,\
DB_USERNAME=bookstoreapp,\
DB_PASSWORD=secret,\
EAP_HTTPS_SECRET=eap-app-secret-member,\
EAP_HTTPS_KEYSTORE=keystore.jks,\
EAP_HTTPS_NAME=jboss,\
EAP_HTTPS_PASSWORD=mykeystorepass,\
VOLUME_CAPACITY=1Gi \
> processed-template.json
[student@workstation ~]$ cp /home/student/DO280/labs/lab-review/process-template.sh .
(2)运行 oc process 命令产生资源定义文件
[student@workstation ~]$ bash process-template.sh
生成后的 processed-template.json 的完整内容如下:
{
"kind": "List",
"apiVersion": "v1beta3",
"metadata": {},
"items": [
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"description": "The web server's http port."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore"
},
"spec": {
"ports": [
{
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"deploymentConfig": "bookstore"
}
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"description": "The web server's https port."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "secure-bookstore"
},
"spec": {
"ports": [
{
"port": 8443,
"targetPort": 8443
}
],
"selector": {
"deploymentConfig": "bookstore"
}
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"description": "Ping service for clustered applications."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-ping"
},
"spec": {
"portalIP": "None",
"ports": [
{
"port": 8888,
"targetPort": 8888
}
],
"selector": {
"deploymentConfig": "bookstore"
}
}
},
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"annotations": {
"description": "The database server's port."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-mysql"
},
"spec": {
"ports": [
{
"port": 3306,
"targetPort": 3306
}
],
"selector": {
"deploymentConfig": "bookstore-mysql"
}
}
},
{
"apiVersion": "v1",
"id": "bookstore-http-route",
"kind": "Route",
"metadata": {
"annotations": {
"description": "Route for application's http service."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-http-route"
},
"spec": {
"host": "bookstore.cloudapps0.example.com",
"to": {
"name": "bookstore"
}
}
},
{
"apiVersion": "v1",
"id": "bookstore-https-route",
"kind": "Route",
"metadata": {
"annotations": {
"description": "Route for application's https service."
},
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-https-route"
},
"spec": {
"host": "bookstore.cloudapps0.example.com",
"tls": {
"termination": "passthrough"
},
"to": {
"name": "secure-bookstore"
}
}
},
{
"apiVersion": "v1",
"kind": "ImageStream",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore"
}
},
{
"apiVersion": "v1",
"kind": "BuildConfig",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore"
},
"spec": {
"output": {
"to": {
"kind": "ImageStreamTag",
"name": "bookstore:latest"
}
},
"source": {
"contextDir": "",
"git": {
"ref": "master",
"uri": "http://workstation.pod0.example.com/bookstore"
},
"type": "Git"
},
"strategy": {
"sourceStrategy": {
"from": {
"kind": "ImageStreamTag",
"name": "jboss-eap6-openshift:6.4",
"namespace": "openshift"
}
},
"type": "Source"
},
"triggers": [
{
"github": {
"secret": "xwrWajXC"
},
"type": "GitHub"
},
{
"generic": {
"secret": "doVsDd7R"
},
"type": "Generic"
},
{
"imageChange": {},
"type": "ImageChange"
}
]
}
},
{
"apiVersion": "v1",
"kind": "DeploymentConfig",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore"
},
"spec": {
"replicas": 1,
"selector": {
"deploymentConfig": "bookstore"
},
"strategy": {
"type": "Recreate"
},
"template": {
"metadata": {
"labels": {
"application": "bookstore",
"deploymentConfig": "bookstore"
},
"name": "bookstore"
},
"spec": {
"containers": [
{
"env": [
{
"name": "DB_SERVICE_PREFIX_MAPPING",
"value": "bookstore-mysql=DB"
},
{
"name": "DB_JNDI",
"value": "java:/jboss/datasources/mysql"
},
{
"name": "DB_USERNAME",
"value": "bookstoreapp"
},
{
"name": "DB_PASSWORD",
"value": "secret"
},
{
"name": "DB_DATABASE",
"value": "bookstoredb"
},
{
"name": "TX_DATABASE_PREFIX_MAPPING",
"value": "bookstore-mysql=DB"
},
{
"name": "DB_MIN_POOL_SIZE",
"value": ""
},
{
"name": "DB_MAX_POOL_SIZE",
"value": ""
},
{
"name": "DB_TX_ISOLATION",
"value": ""
},
{
"name": "OPENSHIFT_DNS_PING_SERVICE_NAME",
"value": "bookstore-ping"
},
{
"name": "OPENSHIFT_DNS_PING_SERVICE_PORT",
"value": "8888"
},
{
"name": "EAP_HTTPS_KEYSTORE_DIR",
"value": "/etc/eap-secret-volume"
},
{
"name": "EAP_HTTPS_KEYSTORE",
"value": "keystore.jks"
},
{
"name": "EAP_HTTPS_NAME",
"value": "jboss"
},
{
"name": "EAP_HTTPS_PASSWORD",
"value": "mykeystorepass"
},
{
"name": "HORNETQ_CLUSTER_PASSWORD",
"value": "CxVGPLVP"
},
{
"name": "HORNETQ_QUEUES",
"value": ""
},
{
"name": "HORNETQ_TOPICS",
"value": ""
}
],
"image": "bookstore",
"imagePullPolicy": "Always",
"name": "bookstore",
"ports": [
{
"containerPort": 8080,
"name": "http",
"protocol": "TCP"
},
{
"containerPort": 8443,
"name": "https",
"protocol": "TCP"
},
{
"containerPort": 8888,
"name": "ping",
"protocol": "TCP"
}
],
"readinessProbe": {
"exec": {
"command": [
"/bin/bash",
"-c",
"/opt/eap/bin/readinessProbe.sh"
]
}
},
"volumeMounts": [
{
"mountPath": "/etc/eap-secret-volume",
"name": "eap-keystore-volume",
"readOnly": true
}
]
}
],
"serviceAccount": "eap-service-account",
"volumes": [
{
"name": "eap-keystore-volume",
"secret": {
"secretName": "eap-app-secret-member"
}
}
]
}
},
"triggers": [
{
"imageChangeParams": {
"automatic": true,
"containerNames": [
"bookstore"
],
"from": {
"kind": "ImageStream",
"name": "bookstore"
}
},
"type": "ImageChange"
}
]
}
},
{
"apiVersion": "v1",
"kind": "DeploymentConfig",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-mysql"
},
"spec": {
"replicas": 1,
"selector": {
"deploymentConfig": "bookstore-mysql"
},
"strategy": {
"type": "Recreate"
},
"template": {
"metadata": {
"labels": {
"application": "bookstore",
"deploymentConfig": "bookstore-mysql"
},
"name": "bookstore-mysql"
},
"spec": {
"containers": [
{
"env": [
{
"name": "MYSQL_USER",
"value": "bookstoreapp"
},
{
"name": "MYSQL_PASSWORD",
"value": "secret"
},
{
"name": "MYSQL_DATABASE",
"value": "bookstoredb"
},
{
"name": "MYSQL_LOWER_CASE_TABLE_NAMES",
"value": ""
},
{
"name": "MYSQL_MAX_CONNECTIONS",
"value": ""
},
{
"name": "MYSQL_FT_MIN_WORD_LEN",
"value": ""
},
{
"name": "MYSQL_FT_MAX_WORD_LEN",
"value": ""
},
{
"name": "MYSQL_AIO",
"value": ""
}
],
"image": "mysql",
"imagePullPolicy": "Always",
"name": "bookstore-mysql",
"ports": [
{
"containerPort": 3306,
"protocol": "TCP"
}
],
"volumeMounts": [
{
"mountPath": "/var/lib/mysql/data",
"name": "bookstore-mysql-pvol"
}
]
}
],
"volumes": [
{
"name": "bookstore-mysql-pvol",
"persistentVolumeClaim": {
"claimName": "bookstore-mysql-claim"
}
}
]
}
},
"triggers": [
{
"imageChangeParams": {
"automatic": true,
"containerNames": [
"bookstore-mysql"
],
"from": {
"kind": "ImageStreamTag",
"name": "mysql:latest",
"namespace": "openshift"
}
},
"type": "ImageChange"
}
]
}
},
{
"apiVersion": "v1",
"kind": "PersistentVolumeClaim",
"metadata": {
"labels": {
"application": "bookstore",
"template": "eap6-mysql-persistent-sti"
},
"name": "bookstore-mysql-claim"
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "1Gi"
}
}
}
}
]
}
(3)发布 application
[student@workstation ~]$ oc create -f processed-template.json
2.7. 等待直到 application build 并且运行,这一步等待时间较长,请耐心
(1)确认 build 启动
[student@workstation ~]$ oc get builds
(2)查看 build 日志:
[student@workstation ~]$ oc build-logs bookstore-1
(3)确认 application 和 database pods 启动:
[student@workstation ~]$ oc get pods
注意: REASON ExitCode:0 表示 build 成功。
2.8. 确认 application 没有启动成功, 因为数据库没有数据
(1)查看 application pod 日志
[student@workstation ~]$ oc logs bookstore-1-m6ynh | tail -n 6
[student@workstation ~]$ oc logs bookstore-1-m6ynh | less
2.9. 为数据库增加数据
(1)转发本地端口到 database pod:
[student@workstation ~]$ oc port-forward -p bookstore-mysql-1-28zyg 13306:3306
(2)新开一个终端, 安装 MySQL client:
[student@workstation ~]$ sudo yum -y install mysql
(3)git 克隆, 获取 SQL script:
[student@workstation ~]$ git clone http://workstation.pod0.example.com/bookstore
(4)运行 SQL script
[student@workstation ~]$ mysql -h127.0.0.1 -ubookstoreapp -psecret -P13306 bookstoredb < bookstore/sql/bookstore.sql
(5)确认 database volume 包含有所有 tables
[root@master ~]# ls /var/export/bookstoredbvol/bookstoredb/
(6)停止本地端口转发
Ctrl + C 终止另一个终端运行的 oc port-forward 进程。
2.10. 强制 OSE 创建一个新的 application pod, 并确认启动成功
(1)删除原来失败的 application pod:
[student@workstation ~]$ oc delete pod bookstore-1-m6ynh
(2)确认一个新的 pod 生成, 并等待其启动成功
[student@workstation ~]$ oc get pod
(3)查看 application pod 日志, 确认连接数据库成功
[student@workstation ~]$ oc logs bookstore-1-wp81p | tail -n 5
3. 访问 Bookstore Application
3.1. 确认 application route 到正确的主机
(1)template 参数 APPLICATION_URL
[student@workstation ~]$ oc describe route bookstore
(2)如果 route host 属性不正确, 可以使用 oc edit 修改
3.2. 访问 application
打开浏览器, 访问 bookstore.cloudapps0.example.com
没有评论:
发表评论