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

305 lines
15 KiB
Markdown
Raw Permalink 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)
两台服务器均为腾讯云CVMVIPVirtual 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 # 设置优先级值范围0254值越大优先级越高最高的为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\_1VRRP实例配置。
* virtual\_serverLVS配置。如果没有配置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的高可用
欢迎你在留言区与我交流讨论,我们下一讲见。