第九周作业

第九周作业

1、nginx实现全栈SSL。要求http rewrite到https协议。

1.1 自签名证书

[11:27:30 root@rocky pc]$ cd /apps/nginx/conf/conf.d/
[11:32:29 root@rocky conf.d]$ openssl req -newkey rsa:4096 -nodes -sha256 -keyout www.yanlinux.org.key -x509 -days 3650 -out www.yanlinux.org.crt
Generating a RSA private key
...................................++++
.....................................++++
writing new private key to 'www.yanlinux.org.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:jiangsu
Locality Name (eg, city) [Default City]:nanjing
Organization Name (eg, company) [Default Company Ltd]:yanlinux.org
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:www.yanlinux.org
Email Address []:
[11:33:21 root@rocky conf.d]$ ll
total 16
-rw-r--r-- 1 root root  147 Nov  3 10:20 mobile.conf
-rw-r--r-- 1 root root  455 Nov  8 11:12 pc.conf
-rw-r--r-- 1 root root 2057 Nov  8 11:33 www.yanlinux.org.crt
-rw------- 1 root root 3272 Nov  8 11:32 www.yanlinux.org.key

1.2 第一个域名的https配置

[11:38:51 root@rocky conf.d]$ vi pc.conf
server {
    listen 80;
    listen 443 ssl;
    ssl_certificate /apps/nginx/conf/conf.d/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/conf/conf.d/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m; #共享缓存20兆
    ssl_session_timeout 10m;                   
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;

}

浏览器测试结果:

1.3 实现多域名

#制作第二个域名对应的key和csr文件
[14:20:25 root@rocky conf.d]$ openssl req -newkey rsa:4096 -nodes -sha256 -keyout m.yanlinux.org.key -x509 -days 3650 -out m.yanlinux.org.crt
Generating a RSA private key
......................................................++++
...............++++
writing new private key to 'm.yanlinux.org.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:jiangsu
Locality Name (eg, city) [Default City]:najing
Organization Name (eg, company) [Default Company Ltd]:yanlinux.org
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:m.yanlinux.org
Email Address []:
[14:22:45 root@rocky nginx]$ ll ssl/
total 16
-rw-r--r-- 1 root root 2049 Nov  8 14:21 m.yanlinux.org.crt
-rw------- 1 root root 3272 Nov  8 14:20 m.yanlinux.org.key
-rw-r--r-- 1 root root 2057 Nov  8 11:33 www.yanlinux.org.crt
-rw------- 1 root root 3272 Nov  8 11:32 www.yanlinux.org.key

#配置第二个域名的配置文件
[14:24:09 root@rocky conf.d]$ vi mobile.conf
server {
    listen 80;
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/m.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/m.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m
    ssl_session_timeout 10m;
    server_name m.yanlinux.org;
    root /apps/nginx/html/mobile;
}

1.4 实现HSTS

[14:33:06 root@rocky conf.d]$ vi pc.conf
server {
    listen 80;
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;  #在首部加上HSTS
    location / { #实现跳转
        if ( $scheme = http ) {
            rewrite ^/(.*)$ https://www.yanlinux.org/$1 redirect;                                      
        }
        root /apps/nginx/html/pc;
    }
}

2、nginx实现动静分离。

#实现静态资源访问10.0.0.28
[16:29:31 root@rocky8 ~]$ ll /usr/share/nginx/html/4.jpg 
-rw-r--r-- 1 root root 308120 Aug 25 19:41 /usr/share/nginx/html/4.jpg
[16:30:33 root@rocky8 ~]$ ll /usr/share/nginx/html/1.png 
-rw-r--r-- 1 root root 18000375 Aug 25 19:54 /usr/share/nginx/html/1.png

#实现动态资源访问10.0.0.38
[16:44:06 root@rocky8 ~]$ mkdir /usr/share/nginx/html/api
[16:48:23 root@rocky8 ~]$ echo /usr/share/nginx/html/api/index.html > /usr/share/nginx/html/api/index.html

#修改代理配置
[16:22:09 root@rocky conf.d]$ vi pc.conf 
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location ~ \.(jpg|png|gif)$ {   
        proxy_pass http://10.0.0.28; #注意有后面的/, 表示置换;没有/,表示附加
        proxy_connect_timeout 10s;                                                                     
    }
}

#测试动态资源
[16:34:39 root@rocky8 ~]$ curl www.yanlinux.org/api -L
/usr/share/nginx/html/api/index.html
#测试静态资源见下图

3、nginx实现防盗链功能。

[14:26:08 root@rocky ~]$ vi /apps/nginx/conf/conf.d/pc.conf
server {
    listen 80;
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/m.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/m.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name m.yanlinux.org;
    root /apps/nginx/html/mobile;
    access_log /apps/nginx/logs/m.yanlinux.org-access.log access_json;       valid_referers none blocked server_names *.yanlinux.com ~\.google\. ~\.baidu\. ~\.bing\. ~\.so\. ;  #定义合法的referer
    if ($invalid_referer) { #假如是使用其他的无效的referer访问,返回状态码403
        return 403 "Forbidden Access";
    }
}

#定义referer.html
[14:28:48 root@rocky ~]$ cat /apps/nginx/html/pc/referer.html
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>盗链</title>
</head>
<body>
<img src="http://www.magedu.com/wp-content/uploads/2017/09/logo.png" >
</body>
</html>

#测试结果见下图

#查看日志文件
[14:30:08 root@rocky ~]$ cat /apps/nginx/logs/m.yanlinux.org-access.log|jq
{
  "@timestamp": "2022-11-09T14:30:57+08:00",
  "host": "10.0.0.8",
  "clientip": "10.0.0.1",
  "size": 16,
  "responsetime": 0.000,
  "upstreamtime": "-",
  "upstreamhost": "-",
  "http_host": "m.yanlinux.org",
  "uri": "/logo.png",
  "xff": "-",
  "referer": "http://www.yanlinux.org/",
  "tcp_xff": "-",
  "http_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35",
  "status": "403"  #403错误
}

4、解析nginx常见的负载均衡算法。

4.1 轮询算法(round robin)(默认)

轮询方式,依次将请求分配到各个后台服务器中,默认的负载均衡方式。

适用于后台机器性能一致的情况。

挂掉的机器可以自动从服务列表中剔除。

[20:58:40 root@proxy ~]$ vi /apps/nginx/conf/conf.d/pc.conf
upstream webserver { #标注两台后端web服务器的地址
    server 10.0.0.28; 
    server 10.0.0.38;
}
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location / {
        proxy_pass http://webserver; #实现负载均衡,填写的是upstream配置块的名称
    }
}
[20:59:11 root@proxy ~]$ nginx -s reload

#客户端10.0.0.18测试,是否实现负载均衡
[21:01:05 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.38 
[21:01:05 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[21:01:06 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.38 
[21:01:07 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28

4.2 加权算法(weight)

根据权重来分发请求到不同的机器中,指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

[21:10:08 root@proxy ~]$ vi /apps/nginx/conf/conf.d/pc.conf
upstream webserver {
    server 10.0.0.28 weight=3; #加上权重
    server 10.0.0.38;
}
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location / {
        proxy_pass http://webserver;
    }
}
[21:11:32 root@proxy ~]$ nginx -s reload
#测试
[21:12:08 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[21:12:09 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[21:12:10 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[21:12:11 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.38 

4.3 ip_hash算法

根据请求者ip的hash值将请求发送到后台服务器中,可以保证来自同一ip的请求被打到固定的机器上,可以解决session问题。

[22:05:57 root@proxy conf.d]$ vi pc.conf
upstream webserver {
    ip_hash; #根据客户端ip调度         
    server 10.0.0.28;
    server 10.0.0.38;
    #server 127.0.0.1 backup;
}
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location / {
        proxy_pass http://webserver;
        #proxy_connect_timeout 10s;
        #proxy_cache off;
        #proxy_cache_key $request_uri;
        #proxy_cache_valid any 5m;
        #add_header X-Cache $upstream_cache_status;
        #proxy_set_header clientip $remote_addr;
    }
}

[22:07:57 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[22:07:58 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[22:07:59 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[22:07:59 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 

4.4 基于任意关键字实现 hash 算法的负载均衡:upstream_hash 模块

通过指定关键字作为 hash key,基于 hash 算法映射到特定的上游服务器中关键字可以含有变量、字符串可以使用 rr 算法的参数

4.4.1 基于源地址hash

[22:05:57 root@proxy conf.d]$ vi pc.conf
upstream webserver {
    hash $remote_addr; #根据客户端ip调度         
    server 10.0.0.28;
    server 10.0.0.38;
    #server 127.0.0.1 backup;
}
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location / {
        proxy_pass http://webserver;
        #proxy_connect_timeout 10s;
        #proxy_cache off;
        #proxy_cache_key $request_uri;
        #proxy_cache_valid any 5m;
        #add_header X-Cache $upstream_cache_status;
        #proxy_set_header clientip $remote_addr;
    }
}

[22:07:57 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[22:07:58 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[22:07:59 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 
[22:07:59 root@rocky8 ~]$ curl www.yanlinux.org
10.0.0.28 

4.4.2 基于cookie的hash

[22:07:54 root@proxy conf.d]$ vi pc.conf
upstream webserver {
    hash $http_cookie;         
    #hash $remote_addr;
    server 10.0.0.28;
    server 10.0.0.38;
    #server 127.0.0.1 backup;
}
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location / {
        proxy_pass http://webserver;
        #proxy_connect_timeout 10s;
        #proxy_cache off;
        #proxy_cache_key $request_uri;
        #proxy_cache_valid any 5m;
        #add_header X-Cache $upstream_cache_status;
        #proxy_set_header clientip $remote_addr;
    }
}

[22:15:20 root@rocky8 ~]$ curl -b 'class=N68' www.yanlinux.org
10.0.0.38 
[22:15:27 root@rocky8 ~]$ curl -b 'class=N67' www.yanlinux.org
10.0.0.28

4.4.3 url_hash

[22:14:26 root@proxy conf.d]$ vi pc.conf
upstream webserver {
    hash $request_uri;  #基于用户请求的uri                        
    #hash $http_cookie;
    #hash $remote_addr;
    server 10.0.0.28;
    server 10.0.0.38;
    #server 127.0.0.1 backup;
}
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location / {
        proxy_pass http://webserver;
        #proxy_connect_timeout 10s;
        #proxy_cache off;
        #proxy_cache_key $request_uri;
        #proxy_cache_valid any 5m;
        #add_header X-Cache $upstream_cache_status;
        #proxy_set_header clientip $remote_addr;
    }
}

[22:15:36 root@rocky8 ~]$ curl www.yanlinux.org/test1.html
test1.html on web02
[22:24:18 root@rocky8 ~]$ curl www.yanlinux.org/test1.html
test1.html on web02
[22:24:27 root@rocky8 ~]$ curl www.yanlinux.org/test4.html
test4.html on web01
[22:24:30 root@rocky8 ~]$ curl www.yanlinux.org/test4.html
test4.html on web01

4.5 最少连接数 least_conn

  • 从所有上游服务器中,找出当前并发连接数最少的一个,将请求转发到它如果出现多个最少连接服务器的连接数都是一样的,使用 rr 算法。适用于客户端与后端服务器需要保持长连接的业务。
  • 模块:ngx_http_upstream_least_conn_module ,通过 --without-http_upstream_ip_hash_module 禁用模块
[22:36:28 root@proxy conf.d]$ vi pc.conf
upstream webserver {
    least_conn;
    #ip_hash                                                                                           
    #hash $request_uri;
    #hash $http_cookie;
    #hash $remote_addr;
    server 10.0.0.28;
    server 10.0.0.38;
    #server 127.0.0.1 backup;
}
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location / {
        proxy_pass http://webserver;
        #proxy_connect_timeout 10s;
        #proxy_cache off;
        #proxy_cache_key $request_uri;
        #proxy_cache_valid any 5m;
        #add_header X-Cache $upstream_cache_status;
        #proxy_set_header clientip $remote_addr;
    }
}

[22:38:28 root@rocky8 ~]$ curl www.yanlinux.org/test4.html
test4.html on web02
[22:38:29 root@rocky8 ~]$ curl www.yanlinux.org/test4.html
test4.html on web01
[22:38:29 root@rocky8 ~]$ curl www.yanlinux.org/test4.html
test4.html on web02

4.6 一致性hash算法

将一个环分成了 2^32 个区间范围,四个节点将这个环划分成为了四个区间,每个区间的请求都由对应的节点去处理。来看看当扩容的时候会发生什么。

假设这时候发现 node4 负载过高,因此决定再添加一个节点进去分担压力,那么影响的也只是这个节点之后的请求,可能会缓存失效,而其他的三个节点是不会有任何影响的。

[22:48:05 root@proxy conf.d]$ vi pc.conf
upstream webserver {
    #least_conn;
    #ip_hash
    hash $request_uri consistent ;                                                                     
    #hash $http_cookie;
    #hash $remote_addr;
    server 10.0.0.28;
    server 10.0.0.38;
    #server 127.0.0.1 backup;
}
server {
    listen 443 ssl;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    root /apps/nginx/html/pc;
    access_log /apps/nginx/logs/www.yanlinux.org-access.log access_json;
    location / {
        proxy_pass http://webserver;
        #proxy_connect_timeout 10s;
        #proxy_cache off;
        #proxy_cache_key $request_uri;
        #proxy_cache_valid any 5m;
        #add_header X-Cache $upstream_cache_status;
        #proxy_set_header clientip $remote_addr;
    }
}

[22:50:44 root@rocky8 ~]$ curl www.yanlinux.org/test4.html
test4.html on web02
[22:50:44 root@rocky8 ~]$ curl www.yanlinux.org/test1.html
test1.html on web01
[22:50:47 root@rocky8 ~]$ curl www.yanlinux.org/test1.html
test1.html on web01
[22:50:48 root@rocky8 ~]$ curl www.yanlinux.org/test4.html
test4.html on web02

5、基于LNMP完成搭建任意一种应用。

5.1 利用 LNMP 实现WordPress站点搭建

LNMP项目实战环境说明

DNS服务器:centos7/10.0.0.7

nginx+php-fpm+wordpress服务器:rocky8/10.0.0.8

mysql服务器:10.0.0.18

5.1.1 部署DNS

[16:39:56 root@centos7 ~]$ cat install_dns.sh
DOMAIN=yanlinux.org
HOST=www
read -p "$(${COLOR}'请输入web服务器IP:'${END})" HOST_IP
#HOST_IP=10.0.0.100

CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


install_dns () {
    if [ $ID = 'centos' -o $ID = 'rocky' ];then
        yum install -y  bind bind-utils
    elif [ $ID = 'ubuntu' ];then
        color "不支持Ubuntu操作系统,退出!" 1
        exit
        #apt update
        #apt install -y  bind9 bind9-utils
    else
        color "不支持此操作系统,退出!" 1
        exit
    fi

}

config_dns () {
    sed -i -e '/listen-on/s/127.0.0.1/localhost/' -e '/allow-query/s/localhost/any/' /etc/named.conf
    cat >>     /etc/named.rfc1912.zones <<EOF
zone "$DOMAIN" IN {
    type master;
    file  "$DOMAIN.zone";
};
EOF
   cat > /var/named/$DOMAIN.zone <<EOF
\$TTL 1D
@    IN SOA    master admin.${DOMAIN} (
                    1    ; serial
                    1D    ; refresh
                    1H    ; retry
                    1W    ; expire
                    3H )    ; minimum
            NS     master
master      A    `hostname -I`         
$HOST         A    $HOST_IP
wordpress   A    $HOST_IP
EOF
   chmod 640 /var/named/$DOMAIN.zone
   chgrp named /var/named/$DOMAIN.zone
}

start_service () {
    systemctl enable --now named
    systemctl is-active named.service
    if [ $? -eq 0 ] ;then 
        color "DNS 服务安装成功!" 0  
    else 
        color "DNS 服务安装失败!" 1
        exit 1
    fi   
}

install_dns
config_dns
start_service

[16:40:16 root@centos7 ~]$ sh install_dns.sh
请输入web服务器IP:10.0.0.8

[16:41:55 root@centos7 ~]$ cat /var/named/yanlinux.org.zone
$TTL 1D
@    IN SOA    master admin.yanlinux.org (
                    1    ; serial
                    1D    ; refresh
                    1H    ; retry
                    1W    ; expire
                    3H )    ; minimum
            NS     master
master      A    10.0.0.7          
www         A    10.0.0.8
wordpress    A    10.0.0.8

5.1.2 部署数据库

#修改主机名
[16:42:33 root@rocky8 ~]$ hostnamectl set-hostname mysql-server.yanlinux.org
#yum安装mysql
[16:43:07 root@mysql-server ~]$ yum -y install mysql-server
[16:47:38 root@mysql-server ~]$ systemctl enable --now mysqld

#创建wordpress数据库,并创建用户及授权
[16:51:45 root@mysql-server ~]$ mysql -e 'create database wordpress;'
[16:53:17 root@mysql-server ~]$ mysql -e "create user wordpress@'10.0.0.%' identified by 'lgq123456';"
[16:53:45 root@mysql-server ~]$ mysql -e "grant all on wordpress.* to  wordpress@'10.0.0.%';"

[16:54:43 root@mysql-server ~]$ mysql -uwordpress -h10.0.0.18 -p
Enter password: 
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| performance_schema |
| wordpress          |
+--------------------+
3 rows in set (0.00 sec)

5.1.3 部署PHP

[16:41:49 root@rocky ~]$ hostnamectl set-hostname proxy.yanlinux.org

[16:58:56 root@proxy ~]$ yum -y install php-fpm php-json php-mysqlnd

#修改php上传限制配置
[17:04:11 root@proxy ~]$ vi /etc/php.ini
post_max_size = 100M #将次行从8M修改为100M
upload_max_filesize = 100M #将此行从2M改为100M

#修改配置文件
[17:14:03 root@proxy ~]$ vi /etc/php-fpm.d/www.conf
user = nginx #修改为nginx
group = nginx #修改为nginx
;listen = /run/php-fpm/www.sock #注释此行
listen = 127.0.0.1:9000 #添加此行,监控本机的9000端口
pm.status_path = /fpm_status #取消此行的注释,并改为fpm_status,防止与nginx服务的status冲突
ping.path = /ping #取消此行的注释
ping.response = pong #取消此行的注释

#启动服务
[17:19:49 root@proxy ~]$ systemctl enable --now php-fpm.service 
Created symlink /etc/systemd/system/multi-user.target.wants/php-fpm.service → /usr/lib/systemd/system/php-fpm.service.

[17:21:59 root@proxy ~]$ ss -ntl
State      Recv-Q      Send-Q           Local Address:Port           Peer Address:Port     Process     
LISTEN     0           128                  127.0.0.1:9000                0.0.0.0:*     #监听端口开启               
LISTEN     0           128                    0.0.0.0:80                  0.0.0.0:*                    
LISTEN     0           128                    0.0.0.0:22                  0.0.0.0:*                    
LISTEN     0           100                  127.0.0.1:25                  0.0.0.0:*                    
LISTEN     0           128                          *:9090                      *:*                    
LISTEN     0           128                       [::]:22                     [::]:*                    
LISTEN     0           100                      [::1]:25                     [::]:*                    
[17:22:04 root@proxy ~]$ ps aux|grep php
root        5501  0.0  1.0 185340 19380 ?        Ss   17:21   0:00 php-fpm: master process (/etc/php-fpm.conf)
nginx       5502  0.0  0.5 201688 10920 ?        S    17:21   0:00 php-fpm: pool www
nginx       5503  0.0  0.5 201688 10924 ?        S    17:21   0:00 php-fpm: pool www
nginx       5504  0.0  0.5 201688 10924 ?        S    17:21   0:00 php-fpm: pool www
nginx       5505  0.0  0.5 201688 10924 ?        S    17:21   0:00 php-fpm: pool www
nginx       5506  0.0  0.5 201688 10924 ?        S    17:21   0:00 php-fpm: pool www

5.1.4 部署nginx

#编译安装
[17:24:38 root@proxy ~]$ cat /data/scripts/install_nginx.sh 
#!/bin/bash
#
#***********************************************************
#Author:            yanli
#Date:              2022-10-25
#FileName:          install_nginx.sh
#Description:        
#***********************************************************

OS_TYPE=`awk -F'[ "]' '/^NAME/{print $2}' /etc/os-release`
OS_VERSION=`awk -F'[".]' '/^VERSION_ID/{print $2}' /etc/os-release`
CPU=`lscpu |awk '/^CPU\(s\)/{print $2}'`
SRC_DIR=/usr/local/src
read -p "$(echo -e '\033[1;32m请输入下载的版本号:\033[0m')" NUM
NGINX_FILE=nginx-${NUM}
NGINX_INSTALL_DIR=/apps/nginx

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "
    elif [ $2 = "failure" -o $2 = "1"  ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo
}

#下载源码
wget_package(){
    [ -e ${NGINX_INSTALL_DIR} ] && { color "nginx 已安装,请卸载后再安装" 1; exit; }
    cd ${SRC_DIR}
    if [ -e ${NGINX_FILE}.tar.gz ];then
        color "源码包已经准备好" 0
    else
        color "开始下载源码包" 0
        wget http://nginx.org/download/${NGINX_FILE}.tar.gz
        [ $? -ne 0 ] && { color "下载 ${NGINX_FILE}.tar.gz文件失败" 1; exit; }
    fi
}

#编译安装
install_nginx(){
    color "开始安装nginx" 0
    if id nginx &> /dev/null;then
        color "nginx用户已经存在" 1
    else
        useradd -s /sbin/nologin -r nginx
        color "nginx用户账号创建完成" 0
    fi

    color "\n开始安装nginx依赖包\n" 0
    if [ $OS_TYPE == "Centos" -a ${OS_VERSION} == '7' ];then
        yum -y install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Centos" -a ${OS_VERSION} == '8' ];then
        yum -y install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Rocky" ];then
        yum -y install make gcc libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Ubuntu" ];then
        apt update
        apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev 
    else
        color '不支持此系统!'  1
        exit
    fi

    #开始编译安装
    color "\n开始编译安装nginx\n" 0
    cd $SRC_DIR
    tar xf ${NGINX_FILE}.tar.gz
    cd ${SRC_DIR}/${NGINX_FILE}
    ./configure --prefix=${NGINX_INSTALL_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
    make -j ${CPU} && make install
    [ $? -eq 0 ] && color "nginx 编译安装成功" 0 ||  { color "nginx 编译安装失败,退出!" 1 ;exit; }
    echo "PATH=${NGINX_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/nginx.sh

    #创建service文件
    cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=${NGINX_INSTALL_DIR}/sbin/nginx -t
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true                                                                                        
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target
EOF

    #启动服务
    systemctl enable --now nginx &> /dev/null
    systemctl is-active nginx &> /dev/null ||  { color "\nnginx 启动失败,退出!\n" 1 ; exit; }
    color "\nnginx 安装完成\n" 0

}

wget_package
install_nginx

[17:27:39 root@proxy ~]$ sh /data/scripts/install_nginx.sh 
请输入下载的版本号:1.22.1

[17:27:47 root@proxy ~]$ systemctl status nginx.service 
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/nginx.service.d
           └─php-fpm.conf
   Active: active (running) since Wed 2022-11-02 09:44:09 CST; 1 weeks 1 days ago
     Docs: http://nginx.org/en/docs/
 Main PID: 4912 (nginx)
    Tasks: 2 (limit: 11217)
   Memory: 1.9M
   CGroup: /system.slice/nginx.service
           ├─4912 nginx: master process /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
           └─4913 nginx: worker process

Nov 02 09:44:07 rocky.lgq.com systemd[1]: Starting nginx - high performance web server...
Nov 02 09:44:09 rocky.lgq.com systemd[1]: nginx.service: Can't open PID file /apps/nginx/run/nginx.pid>
Nov 02 09:44:09 rocky.lgq.com systemd[1]: Started nginx - high performance web server.

#配置nginx支持fastcgi
[17:28:52 root@proxy ~]$ mkdir /apps/nginx/conf/conf.d
[17:29:18 root@proxy ~]$ vi /apps/nginx/conf/nginx.conf
##在http配置块的最后加上下面一行信息
include /apps/nginx/conf/conf.d/*.conf;

[17:30:23 root@proxy ~]$ vi /apps/nginx/conf/conf.d/wordpress.conf
server {
    listen 80;
    server_name wordpress.yanlinux.org;
    client_max_body_size 100M; #搭配5.3.4.2中修改的php.ini实现上传大文件     
    location / {
        root /data/wordpress;
        index index.php index.html index.htm;
    }
    location ~ \.php$ {
        root           /data/wordpress;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
    location ~ ^/(ping|fpm_status)$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}
[17:40:50 root@proxy ~]$ nginx -s reload


#测试php
#结果见下面图片

5.1.5 部署 WordPress

#下载wordpress
[17:58:00 root@proxy ~]$ wget https://cn.wordpress.org/latest-zh_CN.zip
[18:00:13 root@proxy ~]$ unzip latest-zh_CN.zip
[18:00:34 root@proxy ~]$ mkdir /data/wordpress -p
[18:01:06 root@proxy ~]$ mv wordpress/* /data/wordpress
[18:01:19 root@proxy ~]$ chown -R nginx.nginx /data/wordpress/

在浏览器中输入:wordpress.yanlinux.org进行初始化web页面

插入大图片测试是否可以上传

图片17M,发布成功

#可以看到上传的图片
[18:07:14 root@proxy ~]$ tree /data/wordpress/wp-content/uploads/
/data/wordpress/wp-content/uploads/
└── 2022
    └── 11
        └── 1.png

2 directories, 1 file

5.1.6 安全加固以及开启opcache加速

未加固的

[18:26:49 root@proxy ~]$ vi /apps/nginx/conf/conf.d/wordpress.conf
server {
    listen 80;
    server_name wordpress.yanlinux.org;
    client_max_body_size 100M;
    server_tokens off; #添加此行
    location / {
        root /data/wordpress;
        index index.php index.html index.htm;
    }
    location ~ \.php$ {
        root           /data/wordpress;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
        fastcgi_hide_header X-Powered-By; #添加此行
    }
    location ~ ^/(ping|fpm_status)$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}
[18:27:05 root@proxy ~]$ nginx -s reload

#编辑php.ini开启opcache加速
[18:27:06 root@proxy ~]$ vi /etc/php.ini
[opcache]
; Determines if Zend OPCache is enabled
zend_extension=opcache.so
opcache.enable=1

加固

5.2 项目实战:利用LNMP实现可道云私有云

官网: http://kodcloud.com/

5.2.1 部署DNS

#在5.1.1节中的结果中加上一行信息
[21:36:36 root@centos7 ~]$ vi /var/named/yanlinux.org.zone 
$TTL 1D
@   IN SOA  master admin.yanlinux.org (
                    1   ; serial
                    1D  ; refresh
                    1H  ; retry
                    1W  ; expire
                    3H )    ; minimum
            NS   master
master      A    10.0.0.7
www         A    10.0.0.8
wordpress   A    10.0.0.8
kodbox      A    10.0.0.8 #加入这一行对应kodbox网址
[21:37:24 root@centos7 ~]$ rndc reload
server reload successful

5.2.2 部署数据库

#安装在5.1.2基础上另外创建kodbox对应数据库以及账号
[21:30:44 root@mysql-server ~]$ mysql -e 'create database kodbox;'
[21:41:39 root@mysql-server ~]$ mysql -e "create user kodbox@'10.0.0.%' identified by 'lgq123456';"
[21:43:25 root@mysql-server ~]$ mysql -e "grant all on kodbox.* to  kodbox@'10.0.0.%';"
[21:44:14 root@mysql-server ~]$ mysql -e "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| kodbox             |
| mysql              |
| performance_schema |
| sys                |
| wordpress          |
+--------------------+

5.2.3 部署redis

[22:00:40 root@mysql-server ~]$ yum -y install redis
[22:01:19 root@mysql-server ~]$ vi /etc/redis.conf
bind 0.0.0.0 #将此行的127.0.0.1改为0.0.0.0,实现远程访问
[22:02:21 root@mysql-server ~]$ systemctl enable --now redis

5.2.4 部署PHP

#PHP大部分配置参照5.1.3小节,额外需要安装kodbox所需的依赖包
[22:17:15 root@proxy ~]$ yum -y install php-mbstring php-xml php-gd

#安装编译php-redis所依赖的相关包
[22:17:54 root@proxy ~]$ yum -y install php-cli php-devel

#官网下载php-redis,官网https://pecl.php.net/package/redis
[22:27:02 root@proxy ~]$ wget https://pecl.php.net/get/redis-5.3.7.tgz -P /usr/local/src/
[22:29:30 root@proxy src]$ cd /usr/local/src/
[22:29:52 root@proxy src]$ tar xf redis-5.3.7.tgz
[22:30:07 root@proxy src]$ cd redis-5.3.7/
[22:30:29 root@proxy redis-5.3.7]$ phpize
Configuring for:
PHP Api Version:         20170718
Zend Module Api No:      20170718
Zend Extension Api No:   320170718
[22:31:52 root@proxy redis-5.3.7]$ ./configure
[22:33:00 root@proxy redis-5.3.7]$ make -j 2 && make install

[22:33:53 root@proxy redis-5.3.7]$ ll /usr/lib64/php/modules/redis.so 
-rwxr-xr-x 1 root root 3531032 Nov 10 22:33 /usr/lib64/php/modules/redis.so

[22:34:31 root@proxy redis-5.3.7]$ vi /etc/php.d/31-redis.ini
extension=redis #加入此行

#重启
[22:35:58 root@proxy redis-5.3.7]$ systemctl restart php-fpm.service

centos7部署php支持redis安装方法

[root@centos7 ~]$ yum install https://mirror.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm

#安装必要的包
[root@centos7 ~]$ yum -y install php74-php-fpm php74-php-mysqlnd php74-php-pecl-redis5 php74-php-mbstring php74-php-xml php74-php-gd

[root@centos7 ~]$ vim /etc/opt/remi/php74/php-fpm.d/www.conf
user = nginx
group = nginx
listen = 127.0.0.1:9000

#文件最后修改下面两行
php_value[session.save_handler] = redis
php_value[session.save_path] = "tcp://10.0.0.8:6379"

5.2.5 部署nginx

#安装配置nginx参照5.1.4小节,在此基础上配置kodbox对应的fastcgi配置
[21:52:26 root@proxy ~]$ vi /apps/nginx/conf/conf.d/kodbox.conf
server {
    listen 80;
    server_name kodbox.yanlinux.org;
    client_max_body_size 100M;
    server_tokens off;
    location / {
        root /data/kodbox/; 
        index index.php index.html index.htm;
    }
    location ~ \.php$ {
        root           /data/kodbox/;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }
    location ~ ^/(ping|fpm_status)$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

5.2.6 部署kodbox

#下载kodbox
[22:06:01 root@proxy ~]$ wget https://static.kodcloud.com/update/download/kodbox.1.35.zip^C
[22:09:22 root@proxy ~]$ mkdir /data/kodbox
[22:10:08 root@proxy ~]$ unzip kodbox.1.35.zip -d /data/kodbox
[22:10:29 root@proxy ~]$ chown -R nginx.nginx /data/kodbox/

5.2.7 初始化和登录可道云

上传图片测试

6、jumpserver 总结安装部署,添加用户授权,行为审计。

6.1 基于docker安装部署jumpserver

6.1.1 安装docker

[15:21:33 root@rocky ~]$ cat install_docker.sh 
#!/bin/bash
DOCKER_VERSION="20.10.10"
UBUNTU_DOCKER_VERSION="5:${DOCKER_VERSION}~3-0~`lsb_release -si`-`lsb_release -cs`"
#UBUNTU_DOCKER_VERSION="5:20.10.9~3-0~`lsb_release -si`-`lsb_release -cs`"
#UBUNTU_DOCKER_VERSION="5:19.03.14~3-0~lsb_release -si-`lsb_release -cs`"

COLOR_SUCCESS="echo -e \\033[1;32m"
COLOR_FAILURE="echo -e \\033[1;31m"
END="\033[m"

. /etc/os-release

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


install_docker(){
    if [ $ID = "centos" -o $ID = "rocky" ];then
        if [ $VERSION_ID = "7" ];then
            cat >  /etc/yum.repos.d/docker.repo  <<EOF
[docker]
name=docker
gpgcheck=0
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/
EOF
        else     
            cat >  /etc/yum.repos.d/docker.repo  <<EOF
[docker]
name=docker
gpgcheck=0
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/8/x86_64/stable/
EOF
        fi
        yum clean all 
        ${COLOR_FAILURE} "Docker有以下版本"${END}
        yum list docker-ce --showduplicates
        ${COLOR_FAILURE}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
        ${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
        sleep 5
        yum -y install docker-ce-$DOCKER_VERSION docker-ce-cli-$DOCKER_VERSION  \
            || { color "Base,Extras的yum源失败,请检查yum源配置" 1;exit; }
    else
        dpkg -s docker-ce &> /dev/null && $COLOR"Docker已安装,退出" 1 && exit
        apt update || { color "更新包索引失败" 1 ; exit 1; }  
        apt  -y install apt-transport-https ca-certificates curl software-properties-common || \
            { color "安装相关包失败" 1 ; exit 2;  }  
        curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
        add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
        apt update
        ${COLOR_FAILURE} "Docker有以下版本"${END}
        apt-cache madison docker-ce
        ${COLOR_FAILURE}"5秒后即将安装: docker-"${UBUNTU_DOCKER_VERSION}" 版本....."${END}
        ${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
        sleep 5
        apt -y  install docker-ce=${UBUNTU_DOCKER_VERSION} docker-ce-cli=${UBUNTU_DOCKER_VERSION}
    fi
    if [ $? -eq 0 ];then
        color "安装软件包成功"  0
    else
        color "安装软件包失败,请检查网络配置" 1
        exit
    fi

}

config_docker (){
    mkdir -p /etc/docker
    tee /etc/docker/daemon.json <<-'EOF'
{
      "registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
      "insecure-registries":["harbor.magedu.org:80"]
}
EOF
    systemctl daemon-reload
    systemctl enable docker
    systemctl restart docker
    docker version && color "Docker 安装成功" 0 ||  color "Docker 安装失败" 1
}


set_alias (){
    echo 'alias rmi="docker images -qa|xargs docker rmi -f"' >> ~/.bashrc
    echo 'alias rmc="docker ps -qa|xargs docker rm -f"' >> ~/.bashrc
}


install_docker
config_docker 
set_alias
[15:19:39 root@rocky ~]$ sh install_docker.sh

6.1.2 安装MySQL

#在宿主机准备MySQL配置文件
#准备相关目录
[15:24:07 root@rocky ~]$ mkdir -p /etc/mysql/mysql.conf.d
[15:26:12 root@rocky ~]$ mkdir -p /etc/mysql/conf.d

#生成服务器配置文件,指定字符集
[15:27:50 root@rocky ~]$ tee /etc/mysql/mysql.conf.d/mysqld.cnf <<EOF
[mysqld]
pid-file= /var/run/mysqld/mysqld.pid
socket= /var/run/mysqld/mysqld.sock
datadir= /var/lib/mysql
symbolic-links=0
character-set-server=utf8
EOF

#生成客户端配置文件,指定字符集
[15:28:51 root@rocky ~]$ tee /etc/mysql/conf.d/mysql.cnf <<EOF
> [mysql]
> default-character-set=utf8
> EOF

[15:31:04 root@rocky ~]$ tree /etc/mysql/
/etc/mysql/
├── conf.d
│   └── mysql.cnf
└── mysql.conf.d
    └── mysqld.cnf

2 directories, 2 files

#启动 MySQL 容器
[15:36:02 root@rocky ~]$ docker run -d -p 3306:3306 --name mysql --restart always \
-e MYSQL_ROOT_PASSWORD=lgq123456 \
-e MYSQL_DATABASE=jumpserver \
-e MYSQL_USER=jumpserver \
-e MYSQL_PASSWORD=lgq123456 \
-v /data/mysql:/var/lib/mysql \
-v /etc/mysql/mysql.conf.d/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf \
-v /etc/mysql/conf.d/mysql.cnf:/etc/mysql/conf.d/mysql.cnf \
mysql:5.7.30

#验证
[15:44:15 root@rocky8 ~]$ mysql -uroot -h10.0.0.8 -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30 MySQL Community Server (GPL)

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

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 |
| jumpserver         |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

6.1.3 安装redis服务

[15:54:38 root@rocky ~]$ docker run -d -p 6379:6379 --name redis --restart always redis
#验证
[15:57:39 root@rocky8 ~]$ redis-cli -h 10.0.0.8 
10.0.0.8:6379> info
# Server
redis_version:6.2.6
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:b61f37314a089f19
redis_mode:standalone
os:Linux 4.18.0-348.el8.0.2.x86_64 x86_64

6.1.4 部署Jumpserver

6.1.4.1 生成key和token
[16:02:15 root@rocky ~]$ cat key.sh 
#!/bin/bash
if [ ! "$SECRET_KEY" ]; then
    SECRET_KEY=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 50`;
    echo "SECRET_KEY=$SECRET_KEY" >> ~/.bashrc;
    echo SECRET_KEY=$SECRET_KEY;
else
    echo SECRET_KEY=$SECRET_KEY;
fi

if [ ! "$BOOTSTRAP_TOKEN" ]; then
    BOOTSTRAP_TOKEN=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 16`;
    echo "BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN" >> ~/.bashrc;
    echo BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN;
else
    echo BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN;
fi

[16:02:01 root@rocky ~]$ sh key.sh 
SECRET_KEY=aY8gq0orOcO6x2u2pm07UCiuo6hiqwMGBKIE0PRdkq57xJXIGW
BOOTSTRAP_TOKEN=IYkYOKl4Nmw3IgLS
6.1.4.2 运行容器
[16:08:51 root@rocky ~]$ docker run --name jms_all -d \
  -v /opt/jumpserver/core/data:/opt/jumpserver/data \
  -v /opt/jumpserver/koko/data:/opt/koko/data \
  -v /opt/jumpserver/lion/data:/opt/lion/data \
  -p 80:80 \
  -p 2222:2222 \
  -e SECRET_KEY=aY8gq0orOcO6x2u2pm07UCiuo6hiqwMGBKIE0PRdkq57xJXIGW \ #key.sh生成的key
  -e BOOTSTRAP_TOKEN=IYkYOKl4Nmw3IgLS \ #key.sh生成的token
  -e LOG_LEVEL=ERROR \
  -e DB_HOST=10.0.0.8 \ #mysql服务器ip
  -e DB_PORT=3306 \
  -e DB_USER=jumpserver \ #创建的而账号
  -e DB_PASSWORD=lgq123456 \
  -e DB_NAME=jumpserver \
  -e REDIS_HOST=10.0.0.8 \
  -e REDIS_PORT=6379 \
  -e REDIS_PASSWORD='' \
  --privileged=true \
  jumpserver/jms_all
6.1.4.3 验证
[16:14:20 root@rocky ~]$ docker logs -f jms_all 
2022-11-11 16:14:03 Check database connection: 0
2022-11-11 16:14:03 Generating grammar tables from /usr/lib/python3.8/lib2to3/Grammar.txt
2022-11-11 16:14:03 Generating grammar tables from /usr/lib/python3.8/lib2to3/PatternGrammar.txt
2022-11-11 16:14:03 Database connect success
2022-11-11 16:14:03 Collect static files
2022-11-11 16:14:03 Collect static files done
2022-11-11 16:14:03 Check database structure change ...
2022-11-11 16:14:03 Migrate model change to database ...
System check identified no issues (0 silenced).
......
2022-11-11 16:14:20 Fri Nov 11 16:14:20 2022
2022-11-11 16:14:20 JumpServer version v2.17.2, more see https://www.jumpserver.org
Migrate model org id: UserGroupStarting supervisor: supervisord.
Jumpserver ALL v2.17.2
官网 http://www.jumpserver.org
文档 http://docs.jumpserver.org

进入容器命令 docker exec -it jms_all /bin/bash

用户名和密码都是默认admin

修改密码

6.2 用户授权和行为审计

6.2.1 创建组

6.2.2 创建用户并加入组

创建xiaoming用户,并将其加入到development组

创建xiaohong用户,将其加入到test组,并启用双因素认证

登录xiaohong

image-20221111171221489

image-20221111171415649

6.2.3 创建系统审计员

image-20221111171733215

登录查看

6.2.4 创建管理用户

管理用户是jumpServer用来管理后端服务器或其它资产的管理员用户,此用户必须对后端服务器有管理
权限

6.2.5 创建资产并实现资产分类

创建可以被jumpServer用户访问的后端服务器和其它资产,比如:路由器,交换机等

在dev环境中添加一台后端主机

在dev环境分类添加第二台后端主机

在test环境分类加入后端主机

所有创建的后端节点

6.2.6 创建系统用户

系统用户是分配给JumpServer用户,用来让JumpServer用户在连接后端服务器和其它资产,一般不会给管理权限

生产环境中,一般都会利用自动化运维工具提前在后端服务器创建好系统用户,在所有后端服务器统一用户ID信息,而非在jumpserver中创建

创建dev用户

创建test用户

6.2.7 关联使用系统用户的资产

将前面创建的系统用户推送到后端服务器并自动创建
在系统用户中添加使用此用户的资产

image-20221111180409016

添加成功

6.2.8 创建授权规则

通过授权规则, 为JumpServer用户分配可以访问的资产及使用的系统用户

image-20221111180758329

开发组授权

测试组授权

6.2.9 测试登录访问后端服务器

测试组的小红登录

登录管理后端

开发组xiaoming登录管理jumpserver

开发组登录管理后端

6.2.10 ssh连接jumpserver

[16:46:25 root@rocky ~]$ ssh -p2222 xiaoming@127.0.0.1
xiaoming@127.0.0.1's password: 
        xiaoming,  JumpServer 开源堡垒机

    1) 输入 部分IP,主机名,备注 进行搜索登录(如果唯一).
    2) 输入 / + IP,主机名,备注 进行搜索,如:/192.168.
    3) 输入 p 进行显示您有权限的主机.
    4) 输入 g 进行显示您有权限的节点.
    5) 输入 d 进行显示您有权限的数据库.
    6) 输入 k 进行显示您有权限的Kubernetes.
    7) 输入 r 进行刷新最新的机器和节点信息.
    8) 输入 h 进行显示帮助.
    9) 输入 q 进行退出.
Opt> p
  ID    | 主机名                                           | IP                      | 备注            
+-------+--------------------------------------------------+-------------------------+----------------+
  1     | centos7                                          | 10.0.0.7                |                 
  2     | rocky8                                           | 10.0.0.18               |                 
页码:1,每页行数:33,总页数:1,总数量:2
提示:输入资产ID直接登录,二级搜索使用 // + 字段,如://192 上一页:b 下一页:n
搜索:


[18:20:44 root@rocky ~]$ ssh -p2222 xiaohong@127.0.0.1
xiaohong@127.0.0.1's password: 
        xiaohong,  JumpServer 开源堡垒机

    1) 输入 部分IP,主机名,备注 进行搜索登录(如果唯一).
    2) 输入 / + IP,主机名,备注 进行搜索,如:/192.168.
    3) 输入 p 进行显示您有权限的主机.
    4) 输入 g 进行显示您有权限的节点.
    5) 输入 d 进行显示您有权限的数据库.
    6) 输入 k 进行显示您有权限的Kubernetes.
    7) 输入 r 进行刷新最新的机器和节点信息.
    8) 输入 h 进行显示帮助.
    9) 输入 q 进行退出.
Opt> p
  ID    | 主机名                                           | IP                      | 备注            
+-------+--------------------------------------------------+-------------------------+----------------+
  1     | ubuntu2004                                       | 10.0.0.200              |                 
页码:1,每页行数:33,总页数:1,总数量:1
提示:输入资产ID直接登录,二级搜索使用 // + 字段,如://192 上一页:b 下一页:n
搜索:
[Host]> g

节点:[ ID.名称(资产数量) ].
├── 1.收藏夹(0)
└── 2.Default(1)
    └── 3.test环境(1)

6.2.11 查看在线会话

管理员账号管理所有用户的行为

6.2.12 在线回放历史会话

查看回放

6.2.13 查看命令历史

提示执行过的命令以及谁执行的

7、JVM垃圾回收原理,JVM调优。

7.1 JVM垃圾回收原理

分代堆内存GC策略:对不同数据进行区分管理,不同分区对数据实施不同回收策略,分而治之

Heap堆内存分为

  • 年轻代Young:Young Generation
    • 伊甸园区eden: 只有一个,刚刚创建的对象
    • 幸存(存活)区Servivor Space:有2个幸存区,一个是from区,一个是to区。大小相等、地位相同、可互换。
      • from 指的是本次复制数据的源区
      • to 指的是本次复制数据的目标区
  • 老年代Tenured:Old Generation, 长时间存活的对象
  • 永久代:JDK1.7之前使用, 即Method Area方法区,保存JVM自身的类和方法,存储JAVA运行时的环境信息,JDK1.8后 改名为 MetaSpace,此空间不存在垃圾回收,关闭JVM会释放此区域内存,此空间物理上不属于heap内存,但逻辑上存在于heap内存

7.1.1 年轻代回收 Minor GC

  • 起始时,所有新建对象(特大对象直接进入老年代)都出生在eden,当eden满了,启动GC。这个称为Young GC 或者 Minor GC。
  • 先标记eden存活对象,然后将存活对象复制到s0(假设本次是s0,也可以是s1,它们可以调换),eden剩余所有空间都清空。GC完成。
  • 继续新建对象,当eden再次满了,启动GC。
  • 先同时标记eden和s0中存活对象,然后将存活对象复制到s1。将eden和s0清空,此次GC完成
  • 继续新建对象,当eden满了,启动GC。
  • 先标记eden和s1中存活对象,然后将存活对象复制到s0。将eden和s1清空,此次GC完成

以后就重复上面的步骤。

通常场景下,大多数对象都不会存活很久,而且创建活动非常多,新生代就需要频繁垃圾回收。

但是,如果一个对象一直存活,它最后就在from、to来回复制,如果from区中对象复制次数达到阈值(默认15次,CMS为6次,可通过java的选项 -XX:MaxTenuringThreshold=N 指定),就直接复制到老年
代。

7.1.2 老年代回收 Major GC

进入老年代的数据较少,所以老年代区被占满的速度较慢,所以垃圾回收也不频繁。

如果老年代也满了,会触发老年代GC,称为Old GC或者Major GC

由于老年代对象一般来说存活次数较长,所以较常采用标记-压缩算法。

当老年代满时,会触发Full GC,即对所有”代”的内存进行垃圾回收

  • Minor GC比较频繁,Major GC较少。但一般Major GC时,由于老年代对象也可以引用新生代对象,所以先进行一次Minor GC,然后在Major GC会提高效率。可以认为回收老年代的时候完成了一次Full GC。所以可以认为MajorGC = FullGC

7.2 JVM调优

对JVM调整策略应用极广

  • 在WEB领域中Tomcat等
  • 在大数据领域Hadoop生态各组件
  • 在消息中间件领域的Kafka等
  • 在搜索引擎领域的ElasticSearch、Solr等

注意: 在不同领域和场景对JVM需要不同的调整策略

  • 减少 STW 时长,串行变并行
  • 减少 GC 次数,要分配合适的内存大小

一般情况下,大概可以使用以下原则:

  • 客户端或较小程序,内存使用量不大,可以使用串行回收
  • 对于服务端大型计算,可以使用并行回收
  • 大型WEB应用,用户端不愿意等待,尽量少的STW,可以使用并发回收

指定垃圾回收设置

[16:05:26 root@tomcat1 ~]$ vi /usr/local/tomcat/bin/catalina.sh
......
#添加下面一行
JAVA_OPTS="-server -Xmx512m -Xms128m -XX:NewSize=48m -XX:MaxNewSize=200m -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=5"
#在这些行上面添加一行信息
# OS specific support.  $var _must_ be set to either true or false.
cygwin=false
darwin=false
os400=false
hpux=false
......

[16:09:23 root@tomcat1 ~]$ systemctl restart tomcat.service

8、tomcat实现java应用发布。

8.1 部署基于JAVA的博客系统 JPress

官方网站: http://www.jpress.io/

#上官网下载war包,上传到服务器
[16:44:56 root@rocky ~]$ cp jpress-v4.0.7.war /usr/local/tomcat/webapps/jpress.war
[16:45:33 root@rocky ~]$ cd /usr/local/tomcat/webapps/
[16:45:42 root@rocky webapps]$ ls
app1  docs  examples  host-manager  jpress  jpress.war  manager  ROOT

#准备数据库和用户授权
[16:46:56 root@rocky ~]$ yum -y install mysql-server
[16:51:44 root@rocky ~]$ systemctl enable --now mysqld
[16:56:58 root@rocky ~]$ mysql -e "create user jpress@'10.0.0.%' identified by '123456';"
[16:57:40 root@rocky ~]$ mysql -e "create database jpress"
[16:58:12 root@rocky ~]$ mysql -e "grant all on jpress.* to jpress@'10.0.0.%';"

8.2 实战案例:部署博客系统zrlog

官网:ZrLog 博客程序

#官网下载,传到服务器上
[17:51:21 root@rocky ~]$ ls zrlog-2.2.1-efbe9f9-release.war 
zrlog-2.2.1-efbe9f9-release.war
[17:53:30 root@rocky ~]$ cp zrlog-2.2.1-efbe9f9-release.war /usr/local/tomcat/webapps/zrlog.war
[17:53:49 root@rocky ~]$ ls /usr/local/tomcat/webapps/
app1  docs  examples  host-manager  jpress  jpress.war  manager  ROOT  zrlog  zrlog.war

[17:53:50 root@rocky ~]$ mysql -e "create database zrlog;"
[17:57:31 root@rocky ~]$ mysql -e "create user zrlog@'10.0.0.%' identified by 'lgq123456';"
[17:58:00 root@rocky ~]$ mysql -e "grant all on zrlog.* to zrlog@'10.0.0.%';"

9、实现tomcat session粘性,并验证过程。

9.1 负载均衡主机和网络地址规划

IP 主机名 服务 软件
10.0.0.7 dns DNS bind bind-utils
10.0.0.8 调度器 nginx
10.0.0.38 tomcat1 tomcat1 JDK8、tomcat9
10.0.0.28 tomcat1 tomcat2 JDK8、tomcat9

9.2 搭建DNS

[17:12:57 root@dns ~]$ cat install_dns.sh
DOMAIN=yanlinux.org
HOST=www
read -p "$(${COLOR}'请输入web服务器IP:'${END})" HOST_IP
#HOST_IP=10.0.0.100

CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


install_dns () {
    if [ $ID = 'centos' -o $ID = 'rocky' ];then
        yum install -y  bind bind-utils
    elif [ $ID = 'ubuntu' ];then
        color "不支持Ubuntu操作系统,退出!" 1
        exit
        #apt update
        #apt install -y  bind9 bind9-utils
    else
        color "不支持此操作系统,退出!" 1
        exit
    fi

}

config_dns () {
    sed -i -e '/listen-on/s/127.0.0.1/localhost/' -e '/allow-query/s/localhost/any/' /etc/named.conf
    cat >>     /etc/named.rfc1912.zones <<EOF
zone "$DOMAIN" IN {
    type master;
    file  "$DOMAIN.zone";
};
EOF
   cat > /var/named/$DOMAIN.zone <<EOF
\$TTL 1D
@    IN SOA    master admin.${DOMAIN} (
                    1    ; serial
                    1D    ; refresh
                    1H    ; retry
                    1W    ; expire
                    3H )    ; minimum
            NS     master
master      A    `hostname -I`         
$HOST         A    $HOST_IP
EOF
   chmod 640 /var/named/$DOMAIN.zone
   chgrp named /var/named/$DOMAIN.zone
}

start_service () {
    systemctl enable --now named
    systemctl is-active named.service
    if [ $? -eq 0 ] ;then 
        color "DNS 服务安装成功!" 0  
    else 
        color "DNS 服务安装失败!" 1
        exit 1
    fi   
}
install_dns
config_dns
start_service

[17:13:37 root@dns ~]$ sh install_dns.sh

[17:30:20 root@dns ~]$ cat /var/named/yanlinux.org.zone
$TTL 1D
@    IN SOA    master admin.yanlinux.org (
                    1    ; serial
                    1D    ; refresh
                    1H    ; retry
                    1W    ; expire
                    3H )    ; minimum
            NS     master
master      A    10.0.0.7          
www         A    10.0.0.8

9.3 负载均衡tomcat主机准备

  • tomcat1主机准备
[16:37:10 root@tomcat1 ~]$ cat install_tomcat.sh
DIR=`pwd`
read -p "$(echo -e '\033[1;32m请输入JDK版本号:\033[0m')" JDK_VERSION
read -p "$(echo -e '\033[1;32m请输入Tomcat版本号:\033[0m')" TOMCAT_VERSION
JDK_FILE="jdk-${JDK_VERSION}-linux-x64.tar.gz"
TOMCAT_FILE="apache-tomcat-${TOMCAT_VERSION}.tar.gz"
INSTALL_DIR="/usr/local"

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$2" && $MOVE_TO_COL
    echo -n "["
    if [ $1 = "success" -o $1 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "
    elif [ $1 = "failure" -o $1 = "1"  ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo
}

install_jdk(){
    if ! [ -f "${DIR}/${JDK_FILE}" ];then
        color 1 "${JDK_FILE}不存在,请去官网下载"
        exit;
    elif [ -f ${INSTALL_DIR}/jdk ];then
        color 1 "JDK已经安装"
        exit;
    else
        [ -d "${INSTALL_DIR}" ] || mkdir -pv ${INSTALL_DIR}
    fi
    tar xf ${DIR}/${JDK_FILE} -C ${INSTALL_DIR}
    cd ${INSTALL_DIR} && ln -s jdk* jdk

    cat > /etc/profile.d/jdk.sh <<EOF
export JAVA_HOME=${INSTALL_DIR}/jdk
#export JRE_HOME=\$JAVA_HOME/jre
#export CLASSPATH=.:\$JAVA_HOME/lib/:\$JRE_HOME/lib/
export PATH=\$PATH:\$JAVA_HOME/bin
EOF
    . /etc/profile.d/jdk.sh
    java -version && color 0 "JDK安装完成" || { color 1 "JDK安装失败"; exit; }
}

install_tomcat(){
    if ! [ -f "${DIR}/${TOMCAT_FILE}" ];then
        color 1 "${TOMCAT_FILE}不存在,请去官网下载"
        exit;
    elif [ -f ${INSTALL_DIR}/tomcat ];then
        color 1 "tomcat已经安装"
        exit;
    else
        [ -d "${INSTALL_DIR}" ] || mkdir -pv ${INSTALL_DIR}
    fi

    tar xf ${DIR}/${TOMCAT_FILE} -C ${INSTALL_DIR}
    cd ${INSTALL_DIR} && ln -s apache-tomcat-*/ tomcat
    echo "PATH=${INSTALL_DIR}/tomcat/bin:"'$PATH' > /etc/profile.d/tomcat.sh
    id tomcat &> /dev/null || useradd -r -s /sbin/nologin tomcat

    cat > ${INSTALL_DIR}/tomcat/conf/tomcat.conf <<EOF
JAVA_HOME=${INSTALL_DIR}/jdk
EOF

    chown -R tomcat.tomcat ${INSTALL_DIR}/tomcat/

    cat > /lib/systemd/system/tomcat.service <<EOF
[Unit]
Description=Tomcat
#After=syslog.target network.target remote-fs.target nss-lookup.target
After=syslog.target network.target 

[Service]
Type=forking
EnvironmentFile=${INSTALL_DIR}/tomcat/conf/tomcat.conf
ExecStart=${INSTALL_DIR}/tomcat/bin/startup.sh
ExecStop=${INSTALL_DIR}/tomcat/bin/shutdown.sh
RestartSec=3
PrivateTmp=true
User=tomcat
Group=tomcat

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
    systemctl enable --now tomcat.service &> /dev/null
    systemctl is-active tomcat.service &> /dev/null && color 0 "TOMCAT 安装完成" || { color 1 "TOMCAT 安装失败" ; exit; }
}
install_jdk
install_tomcat

[16:37:38 root@tomcat1 ~]$ sh install_tomcat.sh
请输入JDK版本号:8u351
请输入Tomcat版本号:9.0.69
[16:59:27 root@tomcat1 ~]$ systemctl status tomcat.service 
● tomcat.service - Tomcat
   Loaded: loaded (/usr/lib/systemd/system/tomcat.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2022-11-16 16:59:21 CST; 16s ago
  Process: 1680 ExecStart=/usr/local/tomcat/bin/startup.sh (code=exited, status=0/SUCCESS)
 Main PID: 1688 (java)
    Tasks: 27 (limit: 11218)
   Memory: 74.4M
   CGroup: /system.slice/tomcat.service
           └─1688 /usr/local/jdk/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/loggi>

Nov 16 16:59:21 rocky8.yanlinux.cn systemd[1]: Starting Tomcat...
Nov 16 16:59:21 rocky8.yanlinux.cn systemd[1]: Started Tomcat.

#准备数据目录
[17:41:49 root@tomcat1 ~]$ mkdir -p /data/tomcat/node1/ROOT
[17:42:49 root@tomcat1 ~]$ vi /data/tomcat/node1/ROOT/index.jsp
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tomcat test</title>
</head>
<body>
<h1> node1 Website </h1>
<div>On  <%=request.getServerName() %></div>
<div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div>
<div>SessionID = <span style="color:blue"><%=session.getId() %></span></div>
<%=new Date()%>
</body>
</html>
[17:44:15 root@tomcat1 ~]$ tree /data/tomcat/
/data/tomcat/
└── node1
    └── ROOT
        └── index.jsp

2 directories, 1 file
[17:44:33 root@tomcat1 ~]$ chown -R tomcat.tomcat /data/tomcat/

#创建tomcat虚拟主机
[17:44:47 root@tomcat1 ~]$ vi /usr/local/tomcat/conf/server.xml
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
      #添加下面两行
      <Host name="www.yanlinux.org" appBase="/data/tomcat/node1/" unpackWARs="true" autoDeploy="true"> 
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="node1_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      #上面两行时添加的
    </Engine>
  </Service>
</Server>
[17:49:05 root@tomcat1 ~]$ systemctl restart tomcat.service
  • tomcat2主机准备呢
[18:00:38 root@tomcat1 ~]$ sh install_tomcat.sh
请输入JDK版本号:8u351
请输入Tomcat版本号:9.0.69

[18:02:13 root@tomcat2 ~]$ mkdir /data/tomcat/node2/ROOT -p
[18:02:21 root@tomcat2 ~]$ vi /data/tomcat/node2/ROOT/index.jsp
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tomcat test</title>
</head>
<body>
<h1> node2 Website </h1>
<div>On  <%=request.getServerName() %></div>
<div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div>
<div>SessionID = <span style="color:blue"><%=session.getId() %></span></div>
<%=new Date()%>
</body>
</html>
[18:03:54 root@tomcat2 ~]$ chown -R tomcat.tomcat /data/tomcat/


[18:07:05 root@tomcat2 ~]$ vi /usr/local/tomcat/conf/server.xml
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      #添加下面几行
      <Host name="www.yanlinux.org" appBase="/data/tomcat/node2/" unpackWARs="true" autoDeploy="true"> 
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="node2_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      #添加上面几行
    </Engine>
  </Service>
</Server>
[18:14:33 root@tomcat2 ~]$ systemctl restart tomcat.service

9.4 nginx实现后端tomcat的负载均衡调度

[21:12:42 root@nginx-proxy ~]$ cat install_nginx.sh
OS_TYPE=`awk -F'[ "]' '/^NAME/{print $2}' /etc/os-release`
OS_VERSION=`awk -F'[".]' '/^VERSION_ID/{print $2}' /etc/os-release`
CPU=`lscpu |awk '/^CPU\(s\)/{print $2}'`
SRC_DIR=/usr/local/src
read -p "$(echo -e '\033[1;32m请输入下载的版本号:\033[0m')" NUM
NGINX_FILE=nginx-${NUM}
NGINX_INSTALL_DIR=/apps/nginx

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "
    elif [ $2 = "failure" -o $2 = "1"  ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo
}

#下载源码
wget_package(){
    [ -e ${NGINX_INSTALL_DIR} ] && { color "nginx 已安装,请卸载后再安装" 1; exit; }
    cd ${SRC_DIR}
    if [ -e ${NGINX_FILE}.tar.gz ];then
        color "源码包已经准备好" 0
    else
        color "开始下载源码包" 0
        wget http://nginx.org/download/${NGINX_FILE}.tar.gz
        [ $? -ne 0 ] && { color "下载 ${NGINX_FILE}.tar.gz文件失败" 1; exit; }
    fi
}

#编译安装
install_nginx(){
    color "开始安装nginx" 0
    if id nginx &> /dev/null;then
        color "nginx用户已经存在" 1
    else
        useradd -s /sbin/nologin -r nginx
        color "nginx用户账号创建完成" 0
    fi

    color "开始安装nginx依赖包" 0
    if [ $OS_TYPE == "Centos" -a ${OS_VERSION} == '7' ];then
        yum -y install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Centos" -a ${OS_VERSION} == '8' ];then
        yum -y install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Rocky" ];then
        yum -y install make gcc libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Ubuntu" ];then
        apt update
        apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev 
    else
        color '不支持此系统!'  1
        exit
    fi

    #开始编译安装
    color "开始编译安装nginx" 0
    cd $SRC_DIR
    tar xf ${NGINX_FILE}.tar.gz
    cd ${SRC_DIR}/${NGINX_FILE}
    ./configure --prefix=${NGINX_INSTALL_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
    make -j ${CPU} && make install
    [ $? -eq 0 ] && color "nginx 编译安装成功" 0 ||  { color "nginx 编译安装失败,退出!" 1 ;exit; }
    echo "PATH=${NGINX_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/nginx.sh

    #创建service文件
    cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=${NGINX_INSTALL_DIR}/sbin/nginx -t
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true                                                                                        
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target
EOF

    #启动服务
    systemctl enable --now nginx &> /dev/null
    systemctl is-active nginx &> /dev/null ||  { color "nginx 启动失败,退出!" 1 ; exit; }
    color "nginx 安装完成" 0

}
wget_package
install_nginx

[21:13:02 root@nginx-proxy ~]$ sh install_nginx.sh

[21:19:28 root@nginx-proxy ~]$ vi /apps/nginx/conf/nginx.conf
#在最后一个}上面加入以下一行
    include /apps/nginx/conf/conf.d/*.conf;

[21:21:45 root@nginx-proxy ~]$ cd /apps/nginx/conf/
[21:23:34 root@nginx-proxy conf]$ mkdir conf.d
[21:23:43 root@nginx-proxy conf.d]$ vi tomcat.conf
upstream tomcat-server {
    hash $cookie_JSESSIONID; #基于cookie的hash,固定效果
    server 10.0.0.38:8080;
    server 10.0.0.28:8080;
}
server {
    server_name www.yanlinux.org;
    location / {
        root html;
        index index.html index.jsp;
        proxy_pass http://tomcat-server;
        proxy_set_header Host $http_host;
    }
}
[21:37:51 root@nginx-proxy conf.d]$ nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[21:37:58 root@nginx-proxy conf.d]$ nginx -s reload

再次访问还是这个sessionid,和界面

换一个浏览器

10、实现tomcat会话复制集群

IP 主机名 服务 软件
10.0.0.7 dns DNS bind bind-utils
10.0.0.8 调度器 nginx
10.0.0.38 tomcat1 tomcat1 JDK8、tomcat9
10.0.0.28 tomcat1 tomcat2 JDK8、tomcat9

10.1 搭建DNS

[17:12:57 root@dns ~]$ cat install_dns.sh
DOMAIN=yanlinux.org
HOST=www
read -p "$(${COLOR}'请输入web服务器IP:'${END})" HOST_IP
#HOST_IP=10.0.0.100

CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


install_dns () {
    if [ $ID = 'centos' -o $ID = 'rocky' ];then
        yum install -y  bind bind-utils
    elif [ $ID = 'ubuntu' ];then
        color "不支持Ubuntu操作系统,退出!" 1
        exit
        #apt update
        #apt install -y  bind9 bind9-utils
    else
        color "不支持此操作系统,退出!" 1
        exit
    fi

}

config_dns () {
    sed -i -e '/listen-on/s/127.0.0.1/localhost/' -e '/allow-query/s/localhost/any/' /etc/named.conf
    cat >>     /etc/named.rfc1912.zones <<EOF
zone "$DOMAIN" IN {
    type master;
    file  "$DOMAIN.zone";
};
EOF
   cat > /var/named/$DOMAIN.zone <<EOF
\$TTL 1D
@    IN SOA    master admin.${DOMAIN} (
                    1    ; serial
                    1D    ; refresh
                    1H    ; retry
                    1W    ; expire
                    3H )    ; minimum
            NS     master
master      A    `hostname -I`         
$HOST         A    $HOST_IP
EOF
   chmod 640 /var/named/$DOMAIN.zone
   chgrp named /var/named/$DOMAIN.zone
}

start_service () {
    systemctl enable --now named
    systemctl is-active named.service
    if [ $? -eq 0 ] ;then 
        color "DNS 服务安装成功!" 0  
    else 
        color "DNS 服务安装失败!" 1
        exit 1
    fi   
}
install_dns
config_dns
start_service

[17:13:37 root@dns ~]$ sh install_dns.sh

[17:30:20 root@dns ~]$ cat /var/named/yanlinux.org.zone
$TTL 1D
@    IN SOA    master admin.yanlinux.org (
                    1    ; serial
                    1D    ; refresh
                    1H    ; retry
                    1W    ; expire
                    3H )    ; minimum
            NS     master
master      A    10.0.0.7          
www         A    10.0.0.8

10.2 负载均衡tomcat主机准备

10.2.1 tomcat1主机准备

[16:37:10 root@tomcat1 ~]$ cat install_tomcat.sh
DIR=`pwd`
read -p "$(echo -e '\033[1;32m请输入JDK版本号:\033[0m')" JDK_VERSION
read -p "$(echo -e '\033[1;32m请输入Tomcat版本号:\033[0m')" TOMCAT_VERSION
JDK_FILE="jdk-${JDK_VERSION}-linux-x64.tar.gz"
TOMCAT_FILE="apache-tomcat-${TOMCAT_VERSION}.tar.gz"
INSTALL_DIR="/usr/local"

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$2" && $MOVE_TO_COL
    echo -n "["
    if [ $1 = "success" -o $1 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "
    elif [ $1 = "failure" -o $1 = "1"  ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo
}

install_jdk(){
    if ! [ -f "${DIR}/${JDK_FILE}" ];then
        color 1 "${JDK_FILE}不存在,请去官网下载"
        exit;
    elif [ -f ${INSTALL_DIR}/jdk ];then
        color 1 "JDK已经安装"
        exit;
    else
        [ -d "${INSTALL_DIR}" ] || mkdir -pv ${INSTALL_DIR}
    fi
    tar xf ${DIR}/${JDK_FILE} -C ${INSTALL_DIR}
    cd ${INSTALL_DIR} && ln -s jdk* jdk

    cat > /etc/profile.d/jdk.sh <<EOF
export JAVA_HOME=${INSTALL_DIR}/jdk
#export JRE_HOME=\$JAVA_HOME/jre
#export CLASSPATH=.:\$JAVA_HOME/lib/:\$JRE_HOME/lib/
export PATH=\$PATH:\$JAVA_HOME/bin
EOF
    . /etc/profile.d/jdk.sh
    java -version && color 0 "JDK安装完成" || { color 1 "JDK安装失败"; exit; }
}

install_tomcat(){
    if ! [ -f "${DIR}/${TOMCAT_FILE}" ];then
        color 1 "${TOMCAT_FILE}不存在,请去官网下载"
        exit;
    elif [ -f ${INSTALL_DIR}/tomcat ];then
        color 1 "tomcat已经安装"
        exit;
    else
        [ -d "${INSTALL_DIR}" ] || mkdir -pv ${INSTALL_DIR}
    fi

    tar xf ${DIR}/${TOMCAT_FILE} -C ${INSTALL_DIR}
    cd ${INSTALL_DIR} && ln -s apache-tomcat-*/ tomcat
    echo "PATH=${INSTALL_DIR}/tomcat/bin:"'$PATH' > /etc/profile.d/tomcat.sh
    id tomcat &> /dev/null || useradd -r -s /sbin/nologin tomcat

    cat > ${INSTALL_DIR}/tomcat/conf/tomcat.conf <<EOF
JAVA_HOME=${INSTALL_DIR}/jdk
EOF

    chown -R tomcat.tomcat ${INSTALL_DIR}/tomcat/

    cat > /lib/systemd/system/tomcat.service <<EOF
[Unit]
Description=Tomcat
#After=syslog.target network.target remote-fs.target nss-lookup.target
After=syslog.target network.target 

[Service]
Type=forking
EnvironmentFile=${INSTALL_DIR}/tomcat/conf/tomcat.conf
ExecStart=${INSTALL_DIR}/tomcat/bin/startup.sh
ExecStop=${INSTALL_DIR}/tomcat/bin/shutdown.sh
RestartSec=3
PrivateTmp=true
User=tomcat
Group=tomcat

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
    systemctl enable --now tomcat.service &> /dev/null
    systemctl is-active tomcat.service &> /dev/null && color 0 "TOMCAT 安装完成" || { color 1 "TOMCAT 安装失败" ; exit; }
}
install_jdk
install_tomcat

[16:37:38 root@tomcat1 ~]$ sh install_tomcat.sh
请输入JDK版本号:8u351
请输入Tomcat版本号:9.0.69
[16:59:27 root@tomcat1 ~]$ systemctl status tomcat.service 
● tomcat.service - Tomcat
   Loaded: loaded (/usr/lib/systemd/system/tomcat.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2022-11-16 16:59:21 CST; 16s ago
  Process: 1680 ExecStart=/usr/local/tomcat/bin/startup.sh (code=exited, status=0/SUCCESS)
 Main PID: 1688 (java)
    Tasks: 27 (limit: 11218)
   Memory: 74.4M
   CGroup: /system.slice/tomcat.service
           └─1688 /usr/local/jdk/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/loggi>

Nov 16 16:59:21 rocky8.yanlinux.cn systemd[1]: Starting Tomcat...
Nov 16 16:59:21 rocky8.yanlinux.cn systemd[1]: Started Tomcat.

#准备数据目录
[17:41:49 root@tomcat1 ~]$ mkdir -p /data/tomcat/node1/ROOT
[17:42:49 root@tomcat1 ~]$ vi /data/tomcat/node1/ROOT/index.jsp
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tomcat test</title>
</head>
<body>
<h1> node1 Website </h1>
<div>On  <%=request.getServerName() %></div>
<div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div>
<div>SessionID = <span style="color:blue"><%=session.getId() %></span></div>
<%=new Date()%>
</body>
</html>
[17:44:15 root@tomcat1 ~]$ tree /data/tomcat/
/data/tomcat/
└── node1
    └── ROOT
        └── index.jsp

2 directories, 1 file
[17:44:33 root@tomcat1 ~]$ chown -R tomcat.tomcat /data/tomcat/

#创建tomcat虚拟主机
[17:44:47 root@tomcat1 ~]$ vi /usr/local/tomcat/conf/server.xml
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
      #添加下面两行
      <Host name="www.yanlinux.org" appBase="/data/tomcat/node1/" unpackWARs="true" autoDeploy="true"> 
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="node1_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      #上面两行时添加的
    </Engine>
  </Service>
</Server>
[17:49:05 root@tomcat1 ~]$ systemctl restart tomcat.service

10.2.2 tomcat2主机准备呢

[18:00:38 root@tomcat1 ~]$ sh install_tomcat.sh
请输入JDK版本号:8u351
请输入Tomcat版本号:9.0.69

[18:02:13 root@tomcat2 ~]$ mkdir /data/tomcat/node2/ROOT -p
[18:02:21 root@tomcat2 ~]$ vi /data/tomcat/node2/ROOT/index.jsp
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tomcat test</title>
</head>
<body>
<h1> node2 Website </h1>
<div>On  <%=request.getServerName() %></div>
<div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div>
<div>SessionID = <span style="color:blue"><%=session.getId() %></span></div>
<%=new Date()%>
</body>
</html>
[18:03:54 root@tomcat2 ~]$ chown -R tomcat.tomcat /data/tomcat/


[18:07:05 root@tomcat2 ~]$ vi /usr/local/tomcat/conf/server.xml
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      #添加下面几行
      <Host name="www.yanlinux.org" appBase="/data/tomcat/node2/" unpackWARs="true" autoDeploy="true"> 
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="node2_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      #添加上面几行
    </Engine>
  </Service>
</Server>
[18:14:33 root@tomcat2 ~]$ systemctl restart tomcat.service

10.3 nginx实现后端tomcat的负载均衡调度

[21:12:42 root@nginx-proxy ~]$ cat install_nginx.sh
OS_TYPE=`awk -F'[ "]' '/^NAME/{print $2}' /etc/os-release`
OS_VERSION=`awk -F'[".]' '/^VERSION_ID/{print $2}' /etc/os-release`
CPU=`lscpu |awk '/^CPU\(s\)/{print $2}'`
SRC_DIR=/usr/local/src
read -p "$(echo -e '\033[1;32m请输入下载的版本号:\033[0m')" NUM
NGINX_FILE=nginx-${NUM}
NGINX_INSTALL_DIR=/apps/nginx

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "
    elif [ $2 = "failure" -o $2 = "1"  ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo
}

#下载源码
wget_package(){
    [ -e ${NGINX_INSTALL_DIR} ] && { color "nginx 已安装,请卸载后再安装" 1; exit; }
    cd ${SRC_DIR}
    if [ -e ${NGINX_FILE}.tar.gz ];then
        color "源码包已经准备好" 0
    else
        color "开始下载源码包" 0
        wget http://nginx.org/download/${NGINX_FILE}.tar.gz
        [ $? -ne 0 ] && { color "下载 ${NGINX_FILE}.tar.gz文件失败" 1; exit; }
    fi
}

#编译安装
install_nginx(){
    color "开始安装nginx" 0
    if id nginx &> /dev/null;then
        color "nginx用户已经存在" 1
    else
        useradd -s /sbin/nologin -r nginx
        color "nginx用户账号创建完成" 0
    fi

    color "开始安装nginx依赖包" 0
    if [ $OS_TYPE == "Centos" -a ${OS_VERSION} == '7' ];then
        yum -y install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Centos" -a ${OS_VERSION} == '8' ];then
        yum -y install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Rocky" ];then
        yum -y install make gcc libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Ubuntu" ];then
        apt update
        apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev 
    else
        color '不支持此系统!'  1
        exit
    fi

    #开始编译安装
    color "开始编译安装nginx" 0
    cd $SRC_DIR
    tar xf ${NGINX_FILE}.tar.gz
    cd ${SRC_DIR}/${NGINX_FILE}
    ./configure --prefix=${NGINX_INSTALL_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
    make -j ${CPU} && make install
    [ $? -eq 0 ] && color "nginx 编译安装成功" 0 ||  { color "nginx 编译安装失败,退出!" 1 ;exit; }
    echo "PATH=${NGINX_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/nginx.sh

    #创建service文件
    cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=${NGINX_INSTALL_DIR}/sbin/nginx -t
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true                                                                                        
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target
EOF

    #启动服务
    systemctl enable --now nginx &> /dev/null
    systemctl is-active nginx &> /dev/null ||  { color "nginx 启动失败,退出!" 1 ; exit; }
    color "nginx 安装完成" 0

}
wget_package
install_nginx

[21:13:02 root@nginx-proxy ~]$ sh install_nginx.sh



#生成自签名文件
[21:13:58 root@nginx-proxy ~]$ mkdir /apps/nginx/ssl
[21:14:08 root@nginx-proxy ~]$ cd /apps/nginx/ssl
[21:14:25 root@nginx-proxy ssl]$ openssl req -newkey rsa:4096 -nodes -sha256 -keyout m.yanlinux.org.key -x509 -days 3650 -out m.yanlinux.org.crt
Generating a RSA private key
......................................................++++
...............++++
writing new private key to 'm.yanlinux.org.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:jiangsu
Locality Name (eg, city) [Default City]:najing
Organization Name (eg, company) [Default Company Ltd]:yanlinux.org
Organizational Unit Name (eg, section) []:it
Common Name (eg, your name or your server's hostname) []:www.yanlinux.org
Email Address []:
[21:16:45 root@nginx-proxy ssl]$ ll 
-rw-r--r-- 1 root root 2057 Nov  8 21:16 www.yanlinux.org.crt
-rw------- 1 root root 3272 Nov  8 21:16 www.yanlinux.org.key

#创建tomcat对应配置文件
[21:19:28 root@nginx-proxy ~]$ vi /apps/nginx/conf/nginx.conf
#在最后一个}上面加入以下一行
    include /apps/nginx/conf/conf.d/*.conf;

[21:21:45 root@nginx-proxy ssl]$ cd /apps/nginx/conf/
[21:23:34 root@nginx-proxy conf]$ mkdir conf.d
[21:23:43 root@nginx-proxy conf.d]$ vi tomcat.conf
upstream tomcat-server {
    server 10.0.0.38:8080;
    server 10.0.0.28:8080;
}
server {
    listen 80;
    server_name www.yanlinux.org;
    return 302 https://$server_name$request_uri;
}
server {
    listen 443 ssl;
    server_name www.yanlinux.org;
    ssl_certificate /apps/nginx/ssl/www.yanlinux.org.crt;
    ssl_certificate_key /apps/nginx/ssl/www.yanlinux.org.key;
    client_max_body_size 20m;
    location / {
        proxy_pass http://tomcat-server;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
[21:37:51 root@nginx-proxy conf.d]$ nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[21:37:58 root@nginx-proxy conf.d]$ nginx -s reload

10.4 在所有后端tomcat主机上修改conf/server.xml

本次把多播复制的配置放到虚拟主机里面, 即Host块中。

特别注意修改Receiveraddress属性为一个本机可对外的IP地址。

10.4.1 修改 tomcat1 主机的 conf/server.xml

[15:47:22 root@tomcat1 ~]$ vi /usr/local/tomcat/conf/server.xml
     <Host name="www.yanlinux.org" appBase="/data/tomcat/node1/" unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="node1_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
         #下面时添加部分
        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4" #制定一个不冲突的多播地址
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="10.0.0.38"#指定网卡的ip,不然的话默认127.0.0.1       
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>
        #上面是添加部分
      </Host>
[15:54:03 root@tomcat1 ~]$ systemctl restart tomcat.service 
[15:54:22 root@tomcat1 ~]$ ss -ntl
State      Recv-Q     Send-Q              Local Address:Port         Peer Address:Port     Process     
LISTEN     0          128                       0.0.0.0:22                0.0.0.0:*                    
LISTEN     0          50             [::ffff:10.0.0.38]:4000  #监听端口                  *:*                    
LISTEN     0          1              [::ffff:127.0.0.1]:8005                    *:*                    
LISTEN     0          100                             *:8080                    *:*                    
LISTEN     0          128                             *:80                      *:*                    
LISTEN     0          128                          [::]:22                   [::]:*

10.4.2 修改 tomcat2 主机的 conf/server.xml

[16:02:04 root@tomcat2 ~]$ vi /usr/local/tomcat/conf/server.xml 
<Host name="www.yanlinux.org" appBase="/data/tomcat/node2/" unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="node2_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
        <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
                 channelSendOptions="8">

          <Manager className="org.apache.catalina.ha.session.DeltaManager"
                   expireSessionsOnShutdown="false"
                   notifyListenersOnReplication="true"/>

          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Membership className="org.apache.catalina.tribes.membership.McastService"
                        address="228.0.0.4"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="10.0.0.28"                                                              
                      port="4000"
                      autoBind="100"
                      selectorTimeout="5000"
                      maxThreads="6"/>

            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
              <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
            </Sender>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
            <Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
          </Channel>

          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
                 filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

          <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
                    tempDir="/tmp/war-temp/"
                    deployDir="/tmp/war-deploy/"
                    watchDir="/tmp/war-listen/"
                    watchEnabled="false"/>

          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
        </Cluster>
      </Host>

[16:03:13 root@tomcat2 ~]$ systemctl restart tomcat.service 
[16:03:20 root@tomcat2 ~]$ ss -ntl
State      Recv-Q     Send-Q              Local Address:Port         Peer Address:Port     Process     
LISTEN     0          128                       0.0.0.0:22                0.0.0.0:*                    
LISTEN     0          100                             *:8080                    *:*                    
LISTEN     0          128                          [::]:22                   [::]:*                    
LISTEN     0          50             [::ffff:10.0.0.28]:4000 #监听端口                   *:* 

10.5 修改应用的web.xml文件开启该应用程序的分布式

参考官方说明: https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html

Make sure your web.xml has the <distributable/> element

为所有tomcat主机应用web.xml<web-app>标签增加子标签 <distributable/>来开启该应用程序的分布式。

10.5.1 修改tomcat1主机的应用的web.xml文件

[16:07:49 root@tomcat1 ~]$ cp -a /usr/local/tomcat/webapps/ROOT/WEB-INF/  /data/tomcat/node1/ROOT/
[16:07:58 root@tomcat1 ~]$ ll /data/tomcat/node1/ROOT/
total 4
-rw-r--r-- 1 tomcat tomcat 396 Nov 16 19:09 index.jsp
drwxr-x--- 2 tomcat tomcat  21 Nov 16 18:49 WEB-INF

[16:08:01 root@tomcat1 ~]$ vi /data/tomcat/node1/ROOT/WEB-INF/web.xml
......
  <description>
     Welcome to Tomcat
  </description>
<distributable/> #添加此行
</web-app>

[16:09:26 root@tomcat1 ~]$ systemctl restart tomcat.service

10.5.2 修改tomcat2主机的应用的web.xml文件

[16:11:54 root@tomcat2 ~]$ cp -a /usr/local/tomcat/webapps/ROOT/WEB-INF/  /data/tomcat/node2/ROOT/
[16:12:06 root@tomcat2 ~]$ ll /data/tomcat/node2/ROOT/
total 4
-rw-r--r-- 1 tomcat tomcat 396 Nov 16 18:03 index.jsp
drwxr-x--- 2 tomcat tomcat  21 Nov 16 17:00 WEB-INF

[16:12:11 root@tomcat2 ~]$ vi /data/tomcat/node2/ROOT/WEB-INF/web.xml
......
  <description>
     Welcome to Tomcat
  </description>
<distributable/> #添加此行
</web-app>

[16:12:49 root@tomcat2 ~]$ systemctl restart tomcat.service

10.6 测试访问

重启全部Tomcat,通过负载均衡调度到不同节点,返回的SessionID不变了。

用浏览器访问,并刷新多次,发现SessionID 不变,但后端主机在轮询

但此方式当后端tomcat主机较多时,会重复占用大量的内存,并不适合后端服务器众多的场景

10.7 故障模拟

#停掉tomcat2节点,模拟故障
[16:18:35 root@tomcat2 ~]$ systemctl stop tomcat.service

浏览器访问多次,sessionid不发生变化


  转载请注明: 焱黎的博客 第九周作业

  目录