gitbook/Go 语言项目开发实战/docs/411663.md
2022-09-03 22:05:03 +08:00

305 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 40 | 软件部署实战(上):部署方案及负载均衡、高可用组件介绍
你好,我是孔令飞。
接下来,我们就进入到这门课的最后一个模块,服务部署部分的学习。在这一模块中,我会带着你一步一步地部署一个生产级可用的IAM应用。
在 [03讲](https://time.geekbang.org/column/article/378082) 中,我们快速在单机上部署了IAM系统,但这样的系统缺少高可用、弹性扩容等能力,是很脆弱的,遇到流量波峰、发布变更很容易出问题。在系统真正上线前,我们需要重新调整部署架构,来保证我们的系统具有负载均衡、高可用、弹性伸缩等核心运维能力。
考虑到你手中的系统资源有限,这一模块会尽量简单地展示如何部署一个相对高可用的IAM系统。按照我讲的部署方法,基本上可以上线一个中小型的系统。
在这一模块中,我会介绍两种部署方式。
第一种是传统的部署方式,基于物理机/虚拟机来部署,容灾、弹性伸缩能力要部署人员自己实现。第二种是容器化部署方式,基于Docker、Kubernetes来部署,容灾、弹性伸缩等能力,可以借助Kubernetes自带的能力来实现。
接下来的三讲,我们先来看下传统的部署方式,也就是如何基于虚拟机来部署IAM应用。今天我主要讲跟IAM部署相关的两个组件,Nginx + Keepalived的相关功能。
## 部署方案
先来整体看下我们的部署方案。
这里,我采用Nginx + Keepalived来部署一个高可用的架构,同时将组件都部署在内网,来保证服务的安全和性能。
部署需要两台物理机/虚拟机,组件之间通过内网访问。所需的服务器如下表所示:
![图片](https://static001.geekbang.org/resource/image/e0/1d/e0a3323831768fbe7f45085ca4a53a1d.jpg?wh=1920x719)
两台服务器均为腾讯云CVM,VIP(Virtual IP,虚拟IP)为`10.0.4.99`。部署架构如下图所示:
![图片](https://static001.geekbang.org/resource/image/fc/9d/fc5331a780d45a7de6223d6ff3c86f9d.jpg?wh=1920x1197)
这里我来具体介绍下图中的部署架构。部署采用的这两台CVM服务器,一主一备,它们共享同一个VIP。同一时刻,VIP只在一台主设备上生效,当主服务器出现故障时,备用服务器会自动接管VIP,继续提供服务。
主服务器上部署了`iam-apiserver`、`iam-authz-server`、`iam-pump`和数据库`mongodb`、`redis`、`mysql`。备服务器部署了`iam-apiserver`、`iam-authz-server`和`iam-pump`。备服务器中的组件通过内网`10.0.4.20`访问主服务器中的数据库组件。
主备服务器同时安装了Keepalived和Nginx,通过Nginx的反向代理功能和负载均衡功能,实现后端服务`iam-apiserver`和`iam-authz-server`的高可用,通过Keepalived实现Nginx的高可用。
我们通过给虚拟IP绑定腾讯云弹性公网IP,从而使客户端可以通过外网IP访问内网的Nginx服务器(`443`端口),如果想通过域名访问内网,还可以申请域名指向该弹性公网IP。
通过以上部署方案,我们可以实现一个具有较高可用性的IAM系统,它主要具备下面这几个能力。
* 高性能:可以通过Nginx的负载均衡功能,水平扩容IAM服务,从而实现高性能。
* 具备容灾能力:通过Nginx实现IAM服务的高可用,通过Keepalived实现Nginx的高可用,从而实现核心组件的高可用。
* 具备水平扩容能力:通过Nginx的负载均衡功能,实现IAM服务的水平扩容。
* 高安全性:将所有组件部署在内网,客户端只能通过`VIP:443`端口访问Nginx服务,并且通过开启TLS认证和JWT认证,保障服务有一个比较高的安全性。因为是腾讯云CVM,所以也可以借助腾讯云的能力再次提高服务器的安全性,比如安全组、DDoS防护、主机安全防护、云监控、云防火墙等。
这里说明下,为了简化IAM应用的安装配置过程,方便你上手实操,有些能力,例如数据库高可用、进程监控和告警、自动伸缩等能力的构建方式,这里没有涉及到。这些能力的构建方式,你可以在日后的工作中慢慢学习和掌握。
接下来,我们看下这个部署方案中用到的两个核心组件,Nginx和Keepalived。我会介绍下它们的安装和配置方法,为你下一讲的学习做准备。
## Nginx安装和配置
### Nginx功能简介
这里先简单介绍下Nginx。Nginx是一个轻量级、高性能、开源的HTTP服务器和反向代理服务器。IAM系统使用了Nginx反向代理和负载均衡的功能,下面我就来分别介绍下。
为什么需要反向代理呢?在实际的生产环境中,服务部署的网络(内网)跟外部网络(外网)通常是不通的,这就需要一台既能够访问内网又能够访问外网的服务器来做中转,这种服务器就是反向代理服务器。Nginx作为反向代理服务器,简单的配置如下:
```plain
server {
    listen      80;
    server_name  iam.marmotedu.com;
    client_max_body_size 1024M;
    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass  http://127.0.0.1:8080/;
        client_max_body_size 100m;
    }
}
```
Nginx的反向代理功能,能够根据不同的配置规则转发到不同的后端服务器上。假如我们在IP为`x.x.x.x`的服务器上,用上面说的Nginx配置启动Nginx,当我们访问`http://x.x.x.x:80/`时,会将请求转发到`http://127.0.0.1:8080/`。`listen 80`指定了Nginx服务器的监听端口,`proxy_pass http://127.0.0.1:8080/`则指定了转发路径。
Nginx另一个常用的功能是七层负载均衡。所谓的负载均衡,就是指当Nginx收到一个HTTP请求后,会根据负载策略将请求转发到不同的后端服务器上。比如iam-apiserver部署在两台服务器A和B上,当请求到达Nginx后,Nginx会根据A和B服务器上的负载情况,将请求转发到负载较小的那台服务器上。
这里要求iam-apiserver是无状态的服务。Nginx有多种负载均衡策略,可以满足不同场景下的负载均衡需求。
### **Nginx安装步骤**
接下来,我就来介绍下如何安装和配置Nginx。
我们分别在`10.0.4.20`和`10.0.4.21`服务器上执行如下步骤,安装Nginx。
在CentOS 8.x系统上,我们可以使用yum命令来安装,具体安装过程可以分为下面4个步骤。
第一步,安装Nginx:
```bash
$ sudo yum -y install nginx
```
第二步,确认Nginx安装成功:
```bash
$ nginx -v
nginx version: nginx/1.14.1
```
第三步,启动Nginx,并设置开机启动:
```bash
$ sudo systemctl start nginx
$ sudo systemctl enable nginx
```
Nginx默认监听`80`端口,启动Nginx前要确保`80`端口没有被占用。当然,你也可以通过修改Nginx配置文件`/etc/nginx/nginx.conf`修改Nginx监听端口。
第四步,查看Nginx启动状态:
```bash
$ systemctl status nginx
```
输出中有`active (running)`字符串,说明成功启动。如果Nginx启动失败,你可以查看`/var/log/nginx/error.log`日志文件,定位错误原因。
## Keepalived安装和配置
Nginx自带负载均衡功能,并且当Nginx后端某个服务器故障后,Nginx会自动剔除该服务器,将请求转发到可用的服务器,通过这种方式实现后端API服务的高可用。但是 Nginx是单点的,如果Nginx挂了,后端的所有服务器就都不能访问,所以在实际生产环境中,也需要对Nginx做高可用。
业界最普遍采用的方法是通过Keepalived对前端Nginx实现高可用。Keepalived + Nginx的高可用方案具有服务功能强大、维护简单等特点。
接下来,我们来看下如何安装和配置Keepalived。
### Keepalived安装步骤
我们分别在`10.0.4.20`和`10.0.4.21`服务器上执行下面5个步骤,安装Keepalived。
第一步,下载Keepalived的最新版本(这门课安装了当前的最新版本 `2.1.5`):
```bash
$ wget https://www.keepalived.org/software/keepalived-2.1.5.tar.gz
```
第二步,安装Keepalived:
```bash
$ sudo yum -y install openssl-devel # keepalived依赖OpenSSL,先安装依赖
$ tar -xvzf keepalived-2.1.5.tar.gz
$ cd keepalived-2.1.5
$ ./configure --prefix=/usr/local/keepalived
$ make
$ sudo make install
```
第三步,配置Keepalived:
```bash
$ sudo mkdir /etc/keepalived # 安装后,默认没有创建/etc/keepalived目录
$ sudo cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf
$ sudo cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/keepalived
```
Keepalived的systemd uint配置,默认使用了`/usr/local/keepalived/etc/sysconfig/keepalived`作为其`EnvironmentFile`,我们还需要把它修改为`/etc/sysconfig/keepalived`文件。编辑`/lib/systemd/system/keepalived.service`文件,设置`EnvironmentFile`,值如下:
```bash
EnvironmentFile=-/etc/sysconfig/keepalived
```
第四步,启动Keepalived,并设置开机启动:
```bash
$ sudo systemctl start keepalived
$ sudo systemctl enable keepalived
```
这里要注意,Keepalived启动时不会校验配置文件是否正确,所以我们要小心修改配置,防止出现意想不到的问题。
第五步,查看Keepalived的启动状态:
```bash
$ systemctl status keepalived
```
输出中有`active (running)`字符串,说明成功启动。Keepalived的日志保存在`/var/log/messages`中,你有需要的话可以查看。
### Keepalived配置文件解析
Keepalived的默认配置文件为`/etc/keepalived/keepalived.conf`,下面是一个Keepalived配置:
```plain
# 全局定义,定义全局的配置选项
global_defs {
# 指定keepalived在发生切换操作时发送email,发送给哪些email
# 建议在keepalived_notify.sh中发送邮件
  notification_email {
    acassen@firewall.loc
  }
  notification_email_from Alexandre.Cassen@firewall.loc # 发送email时邮件源地址
    smtp_server 192.168.200.1 # 发送email时smtp服务器地址
    smtp_connect_timeout 30 # 连接smtp的超时时间
    router_id VM-4-21-centos # 机器标识,通常可以设置为hostname
    vrrp_skip_check_adv_addr # 如果接收到的报文和上一个报文来自同一个路由器,则不执行检查。默认是跳过检查
    vrrp_garp_interval 0 # 单位秒,在一个网卡上每组gratuitous arp消息之间的延迟时间,默认为0
    vrrp_gna_interval 0 # 单位秒,在一个网卡上每组na消息之间的延迟时间,默认为0
}
# 检测脚本配置
vrrp_script checkhaproxy
{
  script "/etc/keepalived/check_nginx.sh" # 检测脚本路径
    interval 5 # 检测时间间隔(秒)
    weight 0 # 根据该权重改变priority,当值为0时,不改变实例的优先级
}
# VRRP实例配置
vrrp_instance VI_1 {
  state BACKUP  # 设置初始状态为'备份'
    interface eth0 # 设置绑定VIP的网卡,例如eth0
    virtual_router_id 51  # 配置集群VRID,互为主备的VRID需要是相同的值
    nopreempt               # 设置非抢占模式,只能设置在state为backup的节点上
    priority 50 # 设置优先级,值范围0~254,值越大优先级越高,最高的为master
    advert_int 1 # 组播信息发送时间间隔,两个节点必须设置一样,默认为1秒
# 验证信息,两个节点必须一致
    authentication {
      auth_type PASS # 认证方式,可以是PASS或AH两种认证方式
        auth_pass 1111 # 认证密码
    }
  unicast_src_ip 10.0.4.21  # 设置本机内网IP地址
    unicast_peer {
      10.0.4.20             # 对端设备的IP地址
    }
# VIP,当state为master时添加,当state为backup时删除
  virtual_ipaddress {
    10.0.4.99 # 设置高可用虚拟VIP,如果是腾讯云的CVM,需要填写控制台申请到的HAVIP地址。
  }
  notify_master "/etc/keepalived/keepalived_notify.sh MASTER" # 当切换到master状态时执行脚本
    notify_backup "/etc/keepalived/keepalived_notify.sh BACKUP" # 当切换到backup状态时执行脚本
    notify_fault "/etc/keepalived/keepalived_notify.sh FAULT" # 当切换到fault状态时执行脚本
    notify_stop "/etc/keepalived/keepalived_notify.sh STOP" # 当切换到stop状态时执行脚本
    garp_master_delay 1    # 设置当切为主状态后多久更新ARP缓存
    garp_master_refresh 5   # 设置主节点发送ARP报文的时间间隔
    # 跟踪接口,里面任意一块网卡出现问题,都会进入故障(FAULT)状态
    track_interface {
      eth0
    }
  # 要执行的检查脚本
  track_script {
    checkhaproxy
  }
}
```
这里解析下配置文件,大致分为下面4个部分。
* global\_defs:全局定义,定义全局的配置选项。
* vrrp\_script checkhaproxy:检测脚本配置。
* vrrp\_instance VI\_1:VRRP实例配置。
* virtual\_server:LVS配置。如果没有配置LVS+Keepalived,就不用设置这个选项。这门课中,我们使用Nginx代替LVS,所以无需配置`virtual_server`(配置示例中不再展示)。
只有在网络故障或者自身出问题时,Keepalived才会进行VIP切换。但实际生产环境中,我们往往使用Keepalived来监控其他进程,当业务进程出故障时切换VIP,从而保障业务进程的高可用。
为了让Keepalived感知到Nginx的运行状况,我们需要指定`vrrp_script`脚本,`vrrp_script`脚本可以根据退出码,判断Nginx进程是否正常,`0`正常,非`0`不正常。当不正常时,Keepalived会进行VIP切换。为了实现业务进程的监控,我们需要设置`vrrp_script`和`track_script`:
```plain
vrrp_script checkhaproxy
{
    script "/etc/keepalived/check_nginx.sh"
    interval 3
    weight -20
}
vrrp_instance test
{
    ...
    track_script
    {
        checkhaproxy
    }
    ...
}
```
这里,我介绍下上面配置中的一些配置项。
* script:指定脚本路径。
* interval:表示Keepalived执行脚本的时间间隔(秒)。
* weight:检测权重,可以改变`priority`的值。例如,`-20`表示检测失败时,优先级`-20`,成功时不变。`20`表示检测成功时,优先级`+20`,失败时不变。
## 总结
今天我主要讲了跟IAM部署相关的两个组件,Nginx + Keepalived的相关功能。
我们可以基于物理机/虚拟机来部署IAM应用,在部署IAM应用时,需要确保整个应用具备高可用和弹性扩缩容能力。你可以通过Nginx的反向代理功能和负载均衡功能实现后端服务iam-apiserver和iam-authz-server的高可用,通过Keepalived实现Nginx的高可用,通过Nginx + Keepalived组合,来实现IAM应用的高可用和弹性伸缩能力。
## 课后练习
1. Keepalived的主备服务器要接在同一个交换机上。思考下,如果交换机故障,如何实现整个系统的高可用?
2. iam-pump是有状态的服务,思考下,如何实现iam-pump的高可用?
欢迎你在留言区与我交流讨论,我们下一讲见。