使用GitHub管理NGINX配置

NGINX | 2023年12月04日

软件设置、选项和配置有多种不同形式。一端是简洁流畅、响应迅速的GUI,旨在提供直观体验,同时设置防护机制,避免出现无效状态。另一端则是文本文件。文本文件因清晰、易于自动化且使用要求低而受到工程师和DevOps团队的推崇(您现在很可能就开着几个终端窗口,对吧?),但用它们配置软件也存在明显的取舍。例如,很难找到一位从未因文本文件配置错误而导致软件包崩溃的Linux用户。

作为集软件代理、负载均衡器、Web服务器和API网关于一体的解决方案,NGINX是现代互联网基础设施的关键组成部分。这类基础设施大多基于以Linux内核为基础的操作系统。为适应这一生态系统及其运维人员的工作方式,NGINX在很大程度上依赖基于文本的配置。

F5 NGINX Instance Manager模块长期以来一直是编排NGINX相关配置的常用工具。它通过直观的用户界面和API提供高级的远程批量配置管理功能,并配有支持文档和防护机制。不过,单个NGINX配置文件与代码非常相似,而软件团队已经拥有一款出色的代码管理工具:Git。Git为开发和运维团队提供了丰富的功能,专门用于管理文本文件工作流。

Instance Manager新增了与Git及其他外部系统的集成,支持版本控制、分布式贡献、审批工作流和团队协调等功能。GitHub和GitLab等平台通过基于Web的用户界面,将这组功能扩展至持续集成和持续部署(CI/CD)、协作、问题跟踪及其他实用功能。

本文将介绍如何使用GitHub管理NGINX配置,并在配置发生更改时自动将其推送到实例。

Instance Manager API

Instance Manager提供了一套丰富的REST API,作为其Web用户界面的补充。该API的一项主要优势是可以更新受管数据平面实例的配置文件。最近,我们扩展了此功能,支持将配置更新与文件的特定版本关联。配置由Git存储库管理时,可以使用Git提交哈希进行标记。此外,我们还在Instance Manager中为外部管理的配置新增了一种状态,用于提醒准备编辑文件的用户,这些配置由外部管理。

GitHub Actions

GitHub允许开发者使用名为“Actions”的功能,在其存储库中创建自定义部署流水线。用户可以选择定义自己的操作,也可以通过“YAML定义”调用现有脚本。这些流水线可通过多种方式触发,例如提交代码或合并拉取请求导致存储库更新时。

在本博客的示例中,我们使用开箱即用的GitHub Actions和Linux命令。您将了解如何通过Instance Manager API,使用这些工具更新NGINX实例上由GitHub管理的NGINX配置文件。首先,请按照GitHub Docs中的这些步骤操作,创建一个新的YAML文件,以便在存储库中运行Actions。

设置Actions密钥

Instance Manager支持多种身份验证形式。本示例使用基本身份验证方法,但建议在生产环境中配置OIDC身份验证。

无需将Instance Manager凭据存储在存储库中,GitHub允许将定义密钥为存储库变量。Actions环境可以访问这些变量,但日志中不会显示。请按照以下步骤将Instance Manager用户名和密码键存储为密钥,以便使用这些密钥对API调用进行身份验证。

在此,我们将这些变量设置为NMS_USERNAME和NMS_PASSWORD。

技术平台中显示存储库密钥选项的屏幕截图

设置 Actions 变量

同样,与其在YAML中定义常量变量,不如将其提取出来,在GitHub用户界面中统一管理。在变量页面上,可以找到有关如何定义适用于所有仓库Actions的变量的说明。在本示例中,我们借此定义Instance Manager的FQDN或IP(NMS_HOSTNAME)、运行NGINX的系统标识符(SYSTEM_ID),以及要更新的特定NGINX实例的标识符(INSTANCE_ID)。

技术平台中显示存储库变量选项的屏幕截图

注意:为简化示例,我们设置了这些变量,但您也可以选择其他方式来管理Instance Manager、System和NGINX的标识信息。例如,可以在存储库中创建目录,用于存放不同实例的专属配置,并使用系统ID或实例ID为这些目录命名。然后,可以修改YAML或Action脚本,使其读取目录名称,并更新相应实例上的配置文件。

用于更新NGINX配置的Instance Manager REST API调用详解

Instance Manager的配置更新 REST API调用需要多个关键组件才能正常工作。YAML需要定义其中的每个参数,并以正确格式将其封装到API调用中。

本示例使用API调用更新单个实例。不过,也可以在Instance Manager中配置实例组。这样,每当从GitHub推送新配置时,就可以更新组内的所有实例。有关详细信息,请参阅《配置发布操作指南》。

下面详细说明Instance Manager的“配置更新”REST API调用:

https://{INSTANCE MANAGER HOSTNAME}/api/platform/v1/systems/{SYSTEM ID}/instances/{INSTANCE ID}/config' 
--header "accept: application/json" 
--header "Authorization: Basic {LOGIN CREDENTIALS}" 
--header 'Content-Type: application/json'
--data '{
    "configFiles": '{
        "rootDir": "/etc/nginx",
        "files": [{
            "contents": "{NGINX CONFIGURATION FILE}",
            "name": "{PATH TO CONFIGURATION FILE ON SYSTEM}"
        }]
    },
    "externalIdType": "{SOURCE OF CONFIGS}",
    "externalId": "{COMMIT HASH}",
    "updateTime": "{TIMESTAMP}"
}'}'

URI 参数

  • 系统标识符:用于唯一标识运行NGINX的系统的键。在本示例中,此数据在GitHub Actions Variables界面中定义。
  • NGINX实例标识符:用于标识系统中特定NGINX实例的唯一键。在本示例中,此数据在GitHub Actions Variables界面中定义。

标头参数

  • Authorization:Instance Manager用于验证API调用的授权方法和Base64编码凭据。在本示例中,将使用Basic Authorization,凭据数据来自存储库中设置的密钥。

JSON 数据参数

  • configFiles:正在更新的配置文件内容(采用Base64编码),以及这些文件在运行NGINX的系统上的位置。还需要提供NGINX配置文件根目录的路径,最常见的配置为:/etc/nginx。
  • externalIdType:用于向Instance Manager标识配置文件来源的标签。可选值为git或other。在本示例中,我们将此参数硬编码为git。
  • externalId:用于标识配置文件更改的Git提交安全散列算法(SHA)值。
  • updateTime:包含当前日期和时间的字符串,采用%Y-%m-%dT%H:%M:%SZ格式。

Base64编码

为符合Instance Manager的API规范,必须将某些数据编码为Base64格式。现有GitHub Actions没有提供原生实现方式,但可以通过YAML调用Linux工具来完成。

Instance Manager凭据

首先,引用之前定义为密钥的Instance Manager登录凭据,并将其拼接起来。然后,将该字符串转换为Base64编码,并通过echo命令将其作为Linux变量(NMS_LOGIN)输出,再将结果追加到Actions运行器可访问的预定义环境变量(GITHUB_ENV)中。

run: echo "NMS_LOGIN=`echo -n "${{ secrets.NMS_USERNAME }}:${{ secrets.NMS_PASSWORD }}" | base64`" >> $GITHUB_ENV

时间戳

Instance Manager API要求在发送某些API有效负载时包含特定格式的时间戳。可以使用Linux date 命令构造该格式的时间戳。与上一个示例类似,将构造的字符串作为变量添加到Linux环境中。

run: echo "NMS_TIMESTAMP=`date -u +"%Y-%m-%dT%H:%M:%SZ"`" >> $GITHUB_ENV

NGINX 配置

接下来,将计划管理的NGINX配置添加到存储库中。可通过多种方式将文件添加到GitHub存储库。有关详细信息,请参阅GitHub文档中的本指南。要按照示例操作,可以在GitHub存储库中创建与实例相同的目录结构。

下面的YAML条目会从存储库中读取配置文件,将其内容编码为Base64,并像之前一样将结果添加到环境变量中。

run: echo "NGINX_CONF_CONFIG_FILE=`cat nginx-server/etc/nginx/nginx.conf | base64 -w 0`" >> $GITHUB_ENV

在本示例中,我们对GitHub存储库中的每个配置文件重复执行此操作。

整合所有内容

最后,可以使用GitHub的示例参考实现,将所学内容整合为可正常运行的YAML文件。按照该文件中的定义,每当用户通过提交或拉取请求更新存储库时,所有相关的GitHub Actions脚本都会运行。YAML中的最后一个条目将运行curl命令,发出相应的API调用,其中包含Instance Manager更新所有相关配置文件所需的数据。

注意:请在YAML中使用多行run条目(run: |)来运行curl命令,因为这会指示YAML解释器将该条目参数部分中的冒号“:”视为文本。

name: Managing NGINX configs with GitHub and GitHub Actions 
# Controls when the workflow will run 
on: 
  # Triggers the workflow on push or pull request events but only for the "main" branch 
  push: 
    branches: [ "main" ] 
  pull_request: 
    branches: [ "main" ] 
  
  # Allows you to run this workflow manually from the Actions tab 
  workflow_dispatch: 

# A workflow run is made up of one or more jobs that can run sequentially or in parallel 
jobs: 
  # This workflow contains a single job called "build" 
  build: 
    # The type of runner that the job will run on 
    runs-on: ubuntu-latest 

    # Steps represent a sequence of tasks that will be executed as part of the job 
    steps: 
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 
      - uses: actions/checkout@v4 

      - name: Set environment variable for NMS API login credentials 
        run: echo "NMS_LOGIN=`echo -n "${{ secrets.NMS_USERNAME }}:${{ secrets.NMS_PASSWORD }}" | base64`" >> $GITHUB_ENV 

      - name: Set environment variable for NMS API timestamp 
        run: echo "NMS_TIMESTAMP=`date -u +"%Y-%m-%dT%H:%M:%SZ"`" >> $GITHUB_ENV 

      - name: Set environment variable for base64 encoded config file 
        run: echo "NGINX_CONF_CONFIG_FILE=`cat app-sfo-01/etc/nginx/nginx.conf | base64 -w 0`" >> $GITHUB_ENV 

      - name: Set environment variable for base64 encoded config file 
        run: echo "MIME_TYPES_CONFIG_FILE=`cat app-sfo-01/etc/nginx/mime.types | base64 -w 0`" >> $GITHUB_ENV 

      - name: Set environment variable for base64 encoded config file 
        run: echo "DEFAULT_CONF_CONFIG_FILE=`cat app-sfo-01/etc/nginx/conf.d/default.conf | base64 -w 0`" >> $GITHUB_ENV 

      - name: Set environment variable for base64 encoded config file 
        run: echo "SSL_CONF_CONFIG_FILE=`cat app-sfo-01/etc/nginx/conf.d/ssl.conf | base64 -w 0`" >> $GITHUB_ENV 

      - name: API call to Instance Manager 
        run: | 
          curl --location 'https://${{ vars.NMS_HOSTNAME }}/api/platform/v1/systems/${{ vars.SYSTEM_ID }}/instances/${{ vars.INSTANCE_ID }}/config' --header "accept: application/json" --header "Authorization: Basic ${{ env.NMS_LOGIN }}" --header 'Content-Type: application/json' --data '{"configFiles": {"rootDir": "/etc/nginx","files": [{"contents": "${{ env.NGINX_CONF_CONFIG_FILE }}","name": "/etc/nginx/nginx.conf"},{"contents": "${{ env.MIME_TYPES_CONFIG_FILE }}","name": "/etc/nginx/mime.types"},{"contents": "${{ env.DEFAULT_CONF_CONFIG_FILE }}","name": "/etc/nginx/conf.d/default.conf"},{"contents": "${{ env.SSL_CONF_CONFIG_FILE }}","name": "/etc/nginx/conf.d/ssl.conf"}]},"externalIdType": "git","externalId": "${{ github.sha }}","updateTime": "${{ env.NMS_TIMESTAMP }}"}' 

NGINX参考实现

文件发生更改后,可以通过多种方式执行配置更新 API调用。对于GitHub用户,GitHub Actions是较为便捷的方法,但不适用于GitLab或独立Git实现。为满足这些使用场景,我们开发了配套的shell脚本参考实现,可通过命令行触发,也可由自定义脚本调用。

总之,Instance Manager API的新扩展提供了一款功能强大的工具,可采用现代化的去中心化方式管理配置更新、回滚和版本历史记录。将该扩展与GitHub等第三方文本文件和代码管理平台结合使用,可通过直观的Web用户界面获得更多工作流、CI/CD、协作和问题跟踪功能。

欢迎分享您的想法!不妨试用一下,并在评论区留言,或加入我们的NGINX Community Slack频道,告诉我们您的使用感受。


分享
标签: F5 NGINX, Tech

相关博客文章

NGINX Plus R26 正式发布
NGINX | 2022/02/15

NGINX Plus R26 正式发布

NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。

使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
NGINX | 2022/02/10

使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击

gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。

Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
NGINX | 2021/09/13

Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划

了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。

NGINX Plus R19 正式发布
NGINX | 2019/09/03

NGINX Plus R19 正式发布

NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。

NGINX现已正式加入F5
NGINX | 2019/05/09

NGINX现已正式加入F5

NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。

使用NGINX和NGINX Plus实现高性能缓存
NGINX | 2016/08/24

使用NGINX和NGINX Plus实现高性能缓存

我将介绍NGINX在内容缓存和性能方面的工作原理,并分享一些控制NGINX内容缓存方式的技巧。