Ubuntu TechHive
devops-from-scratch-manual-process.md
从零开始的 DevOps(手动流程)
article.细节

从零开始的 DevOps(手动流程)

reading.进展 11 分钟阅读数

从零开始构建 DevOps(含手动流程)的说明

从零开始的 DevOps(手动流程)

Web 应用程序

graph LR
  A[开始] --> B{出错?};
  B -->|是| C[嗯...];
  C --> D[调试];
  D --> B;
  B ---->|否| E[耶!];

设置与依赖

使用 Pyenv 和 Poetry 管理 Python 依赖

首先,让我们在您的系统上安装 Pyenv。然后,让我们选择一个较新的 Python 版本,以便为我们的“从零开始的 DevOps(手动流程)”设置一个由 Poetry 管理的虚拟环境

#!/bin/bash
set -x #echo on

PYTHON_VERSION=3.11.1

echo "正在设置 Python v$PYTHON_VERSION"

echo $PYTHON_VERSION > .python-version
pyenv install $PYTHON_VERSION
pyenv global $PYTHON_VERSION
pyenv local $PYTHON_VERSION
pyenv shell $PYTHON_VERSION

echo "Poetry 安装与虚拟环境创建"

pyenv exec pip install poetry
pyenv exec poetry init
pyenv exec poetry install
pyenv exec poetry shell

echo "将 Python 依赖安装到虚拟环境中"

pyenv exec poetry add black --group dev # 添加开发依赖

echo "虚拟环境可视化检查"

pyenv exec poetry show -v
pyenv exec poetry env info -p
#!/bin/bash
set -x #echo on

pyenv exec poetry run python $@
[tool.poetry]
name = "devops-from-scratch-manual-process"
version = "0.1.0"
description = "DevOps from Scratch (Manual Setup)"
authors = ["user "]
license = "MIT"
readme = "README.md"
#packages = [{include = "devops_from_scratch_manual_process"}]

[tool.poetry.dependencies]
python = "^3.10.6"
#python = "^3.11"
Django = "^4.2"
django-debug-toolbar = "^4.0"
sortedcontainers = "^2.4.0"
httpx = "^0.23.0"
whitenoise = "^6.2.0"
fontawesomefree = "^6.4.0"
typer = { version = "^0.9.0", extras = ["all"] }
markdown = "^3.4.3"

#[tool.poetry.group.dev.dependencies]
#black = "^23.3.0"
#pytest = "7.3.1"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
应用程序命令行界面 (CLI)

CLI 将帮助我们触发 Web 应用程序的管理任务。

import typer

app = typer.Typer()

@app.command()
def hello(name: str):
    print(f"Hello {name}")

@app.command()
def goodbye(name: str, formal: bool = False):
    if formal:
        print(f"Goodbye Mr/Ms {name}. Have a good day.")
    else:
        print(f"Bye {name}!")

Web 应用程序

Markdown 解析器
from typing import List
from pathlib import Path
from markdown import markdown

def parseMarkdownPosts(path: str) -> List[str]:
    p = Path(path)
    mdFilePaths = list(p.glob('**/*.md'))
    postsHtml = [_parseMarkdown(filePath) for filePath in mdFilePaths]
    return postsHtml

def _parseMarkdown(path: str) -> str:
    data = Path(path).read_text()
    html = markdown(data)
    return html
---
title: My First Post
---

# 我的第一篇文章

欢迎来到我的博客!这是我的第一篇文章。

## 一些 Markdown 特性

- * 粗体: **粗体文本**
- * 斜体: *斜体文本*
- * 删除线: ~~删除线文本~~
- * [链接](https://example.com)
---
title: My Second Post
---

# 我的第二篇文章

这是我的第二篇文章,位于嵌套目录中。

从 CLI 处理 Markdown 文件

@app.command()
def markdown(mrkdwndir: str):
    import sys
    from pathlib import Path

    current_dir = Path(__file__).parent.resolve()
    sys.path.insert(1, current_dir)

    from services.postsvc import parseMarkdownPosts

    print(f"正在递归解析目录中的 Markdown 文件: {mrkdwndir}")
    postsHtml = parseMarkdownPosts(mrkdwndir)
    for html in postsHtml:
        print(html)

if __name__ == "__main__":
    app()
Django 框架

让我们实现一个由数据库支持的简单 TODO 列表应用程序。

#!/bin/bash
set -x #echo on

pyenv exec poetry run django-admin startproject $@
./scripts/local/new-django.sh mytodos
更多

让我们忽略不需要的文件:

# Project
__pycache__
.idea
*.sqlite3
*.pem
*.log
perf-report.html

MyTODOs 项目

# 空!!!!

ASGI

"""
mytodos 项目的 ASGI 配置。

它将 ASGI 可调用对象公开为名为 ``application`` 的模块级变量。

有关此文件的更多信息,请参阅
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mytodos.settings")

application = get_asgi_application()

WSGI

"""
mytodos 项目的 WSGI 配置。

它将 WSGI 可调用对象公开为名为 ``application`` 的模块级变量。

有关此文件的更多信息,请参阅
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mytodos.settings")

application = get_wsgi_application()

设置 (SETTINGS)

"""
mytodos 项目的 Django 设置。

由 'django-admin startproject' 使用 Django 4.2 生成。

有关此文件的更多信息,请参阅
https://docs.djangoproject.com/en/4.2/topics/settings/

有关设置及其值的完整列表,请参阅
https://docs.djangoproject.com/en/4.2/ref/settings/
"""

from pathlib import Path

# 在项目内部构建路径,例如:BASE_DIR / 'subdir'。
BASE_DIR = Path(__file__).resolve().parent.parent


# 快速开发设置 - 不适合生产环境
# 请参阅 https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/

# 安全警告:保持生产环境中使用的密钥机密!
SECRET_KEY = "django-insecure-r3#=zp=^#5ehd-*ulh0v&x+b3y$lycz=4-=+=_2nn#cipqi8rl"

# 安全警告:不要在生产环境中开启调试模式!
DEBUG = True

ALLOWED_HOSTS = []


# 应用程序定义

INSTALLED_APPS = [
    "fontawesomefree", # 免费字体
    "crud.apps.CrudConfig", # TODO 的 CRUD
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

ROOT_URLCONF = "mytodos.urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

WSGI_APPLICATION = "mytodos.wsgi.application"


# 数据库
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    }
}


# 密码验证
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]


# 国际化
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_TZ = True


# 静态文件 (CSS, JavaScript, 图片)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = "static/"

# 默认主键字段类型
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
None

URL 配置

"""
mytodos 项目的 URL 配置。

`urlpatterns` 列表将 URL 路由到视图。有关更多信息,请参阅:
    https://docs.djangoproject.com/en/4.2/topics/http/urls/
示例:
函数视图
    1. 添加导入:  from my_app import views
    2. 添加 URL 到 urlpatterns:  path('', views.home, name='home')
基于类的视图
    1. 添加导入:  from other_app.views import Home
    2. 添加 URL 到 urlpatterns:  path('', Home.as_view(), name='home')
包含另一个 URLconf
    1. 导入 include() 函数: from django.urls import include, path
    2. 添加 URL 到 urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("", include("crud.urls", namespace="crud")),
    path("admin/", admin.site.urls),
]

从 CLI 管理 Django 项目

#!/usr/bin/env python
"""Django 用于管理任务的命令行工具。"""
import os
import sys


def main():
    """运行管理任务。"""
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mytodos.settings")
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "无法导入 Django。您确定它已安装并可在您的 PYTHONPATH 环境变量中找到吗?"
            "您是否忘记激活虚拟环境了?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == "__main__":
    main()

新建 Django 应用

#!/bin/bash
set -x #echo on

pyenv exec poetry run `pwd`/manage.py startapp $@

新建一个名为 CRUD 的应用,用于执行 CRUD 操作以帮助跟踪我们的 TODO:

./scripts/local/new-django-app.sh crud

建模 TODO

from django.db import models

# 在此处创建您的模型

class Todo(models.Model):
    name = models.CharField(max_length=100)
    complete = models.BooleanField(default=False)
    #created_at = models.DateTimeField('Created', auto_now_add=True)
    #updated_at = models.DateTimeField('Updated', auto_now=True)

    def __str__(self):
        return self.name

TODO 端点

from django.shortcuts import render, get_object_or_404, redirect
from django.views import generic
from django.http import HttpResponseRedirect

# 在此处创建您的视图。

from .models import Todo

class IndexView(generic.ListView):
    template_name = 'crud/index.html'
    context_object_name = 'todo_list'

    def get_queryset(self):
        """返回所有最新的 crud。"""
        return Todo.objects.order_by('-name')

    #def get_queryset(self):
    #    """返回所有最新的 crud。"""
    #    return Todo.objects.order_by('-created_at')

def add(request):
    name = request.POST['name']
    Todo.objects.create(name=name)

    return redirect('crud:index')

def delete(request, todo_id):
    todo = get_object_or_404(Todo, pk=todo_id)
    todo.delete()

    return redirect('crud:index')

def update(request, todo_id):
    todo = get_object_or_404(Todo, pk=todo_id)
    complete = request.POST.get('complete', False)
    if complete == 'on':
        complete = True

    todo.complete = complete

    todo.save()
    return redirect('crud:index')

TODO 模板

{% load static %}

<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <title>我的 TODOstitle>

    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

    
    
    

    
    <link href="{% static 'fontawesomefree/css/fontawesome.css' %}" rel="stylesheet" type="text/css">
    <link href="{% static 'fontawesomefree/css/brands.css' %}" rel="stylesheet" type="text/css">
    <link href="{% static 'fontawesomefree/css/solid.css' %}" rel="stylesheet" type="text/css">

    
    <script src="https://unpkg.com/htmx.org@1.9.2">script>
  head>
  <body>
    {% block content %}
    <h1>你好,世界!h1>
    {% endblock %}

    
    <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous">script>
    
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous">script>
  body>
html>
{% extends 'crud/base.html' %}

{% block content %}
<div class="container">

  
  <div class="row">
    <div class="offset-md-2 col-lg-9">
      <div class="page-header">
        <h1>
          Todo 列表
        h1>
      div>
    div>
  div>

  
  <div class="row">
    <div class="offset-md-2 col-lg-9">
      <form method="post" action="{% url 'crud:add' %}">
        {% csrf_token %}
        <div class="form-row">
          <div class="col-md-6">
            <input type="text" class="form-control" name="name" placeholder="洗衣服" required>
          div>
          <div class="col-md-6">
            <button type="submit" name="submit" class="btn btn-outline-primary">
              添加
            button>
          div>
        div>
      form>
    div>
  div>
  <hr />

  
  <div class="row">
    <div class="offset-md-2 col-lg-6">
      <div class="list-group">
        {% for todo in todo_list %}
        <div class="list-group-item {% if todo.complete %} todo-complete {% endif %}">
          <form style="display: inline;" method="post" action="{% url 'crud:update' todo.id %}">
            {% csrf_token %}
            <input type="checkbox" name="complete" onchange="this.form.submit()" {% if todo.complete %} checked
              {% endif %} class="todo-status-checkbox"
              title="{% if not todo.complete %} 标记为完成 {% else %} 标记为未完成 {% endif %}">
          form>
          {{ todo.name }}
          <a href="{% url 'crud:delete' todo.id %}" title="删除">
            <i class="far fa-trash-alt">i>
          a>
        div>
        {% endfor %}
      div>
    div>
  div>
div>

{% endblock %}

URL 配置

CRUD Urls

from django.urls import path
from . import views

app_name='todos'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('/delete', views.delete, name='delete'),
    path('/update', views.update, name='update'),
    path('add/', views.add, name='add')
]

迁移数据库

./scripts/local/pyrun.sh ./manage.py migrate

为 MyTODOs CRUD 生成迁移文件

./scripts/local/pyrun.sh ./manage.py makemigrations crud

为 MyTODOs CRUD 创建表

./scripts/local/pyrun.sh ./manage.py migrate
Lightsail 部署

让我们在 AWS 上配置一台经济实惠的虚拟机:

  • 导航至 AWS Lightsail 以创建虚拟机
  • 让我们选择一台运行较新版本 Ubuntu – Jammy Jellyfish (22.04 LTS) 的虚拟机
  • 使用 SSHPEM 密钥连接到虚拟机
  • 以非常原始且危险的方式设置和配置虚拟机
  • 将应用程序文件传输到虚拟机
  • 确保项目持续运行 (nohup vs supervisor)

下载用于安全 SSH 和 SCP 连接到虚拟机的 PEM 密钥

chmod 400 mytodos-on-ubuntu-key.pem
#!/bin/bash
set -x #echo on

ssh -i `pwd`/$1.pem $2@$3
#!/bin/bash
set -x #echo on

# 我是谁?
whoami

# 检查 Python
which python3 # python3 在较新版本的 Ubuntu 上是预装的
which pip3 # 检查是否安装了 python3-pip
which poetry # 检查是否安装了 python3-poetry

# 更新 Ubuntu 软件包注册表列表
sudo apt update

# 安装 Poetry
sudo apt install python3-pip python3-poetry
#!/bin/bash
set -x #echo on

scp -i `pwd`/$1.pem -r $2 $3@$4:$5 # -r 用于递归复制文件
[inet_http_server]
port = 0.0.0.0:9001
username = user
password = 1234

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisord]
serverurl=http://0.0.0.0:9001

[program:mytodos]
directory = /home/ubuntu/mytodos_app
command = sudo poetry run python manage.py runserver 0.0.0.0:80
autostart = true
autorestart = true
#stderr_logfile = /var/log/mytodos/app.err.log
#stdout_logfile = /var/log/mytodos/app.out.log

性能测试

import http from 'k6/http';
import { sleep, check } from 'k6';
import { htmlReport } from 'https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js';
import { textSummary } from 'https://jslib.k6.io/k6-summary/0.0.1/index.js';
export let options = {
  // vus: 100,
  // duration: '30s',
  // iterations: 10,
  // minIterationDuration: '10s',
  stages: [
    { duration: '25s', target: 32 }, // 4 PODS
    { duration: '1m', target: 80 }, // 4 PODS
    // { duration: '300s', target: 800 },
    // { duration: '600s', target: 1200 },
    // { duration: '14m40s', target: 4000 },
    // { duration: '4m40s', target: 1600 },
    // { duration: '8m40s', target: 8000 },
    // { duration: '14m40s', target: 18000 }, Perf Box dies that High
    { duration: '15s', target: 0 },
  ],
  // batch: 8000,
  // batch: 4000,
  batch: 100,
  // batch: 1200,
  // batchPerHost: 18000000,
  batchPerHost: 1440000,
  // batchPerHost: 640000000,
  noConnectionReuse: false,
  // noConnectionReuse: true,
  discardResponseBodies: true,
};

let requestHeaders = {
  'User-Agent': 'k6',
  'Accept': 'application/json',
  // 'Content-Type': 'application/json',
  // 'Authorization': 'Bearer {{ .Jwt }}',
  'X-Consumer-Username': 'k6-Benchmarker',
};

export default function () {
  const res = http.get(
      'http://3.96.193.218',
      {headers: requestHeaders}
  );
  // sleep(1);
  const checkRes = check(res, {
    'status is 200': (r) => r.status === 200,
    // 'response body': (r) => r.body.indexOf('Feel free to browse') !== -1,
  });
}

export function handleSummary(data) {
  return {
    './perf-report.html': htmlReport(data),
    stdout: textSummary(data, { indent: ' ', enableColors: true }),
  };
}

英语

幻灯片

Webapp:
工具:

我们将使用 Django Web 框架来创建一个简单的 TODO 应用程序。Django 是一个高级 Python Web 框架,能够实现快速开发和简洁、务实的设计。您可以访问官方网站了解更多关于 Django 的信息:https://www.djangoproject.com/

演讲者笔记:

我们的演讲者将介绍我们将要构建和部署的 Web 应用程序,解释其目的以及与 DevOps 工作流程的相关性。

构建与测试:
工具:

为了构建和测试我们的 Web 应用程序,我们将使用 Python Poetry 和 Pytest。Poetry 是一个 Python 依赖管理工具,简化了包管理过程。Pytest 是一个流行的测试框架,可以轻松编写和运行单元测试。您可以访问官方网站了解更多关于 Python Poetry 的信息:https://python-poetry.org/,以及在这里了解更多关于 Pytest 的信息:https://pytest.org/

演讲者笔记:

我们将逐步介绍构建和测试应用程序的过程,强调测试的重要性以及它如何融入 DevOps 工作流程。

虚拟机配置:
工具:

我们将使用 AWS Lightsail 和 Bash 来配置我们的虚拟机。AWS Lightsail 是一个简化的云平台,可以轻松启动和管理虚拟专用服务器、存储和网络。Bash 是一种 Unix shell 和命令语言,广泛用于 DevOps 工作流程。您可以在此处了解更多关于 AWS Lightsail 的信息:https://aws.amazon.com/lightsail/,以及在此处了解关于 Bash 的信息:https://www.gnu.org/software/bash/

演讲者笔记:

我们的演讲者将讨论为托管应用程序配置虚拟机的过程,解释可用的不同选项以及如何为您的需求选择最佳选项。

数据库配置:
工具:

对于我们的数据库配置,我们将使用 AWS Lightsail PostgreSQL 或 CockroachDB 作为替代方案。PostgreSQL 是一个功能强大的开源关系数据库管理系统,广泛用于 Web 应用程序开发。CockroachDB 是一个专为可扩展性和弹性而设计的分布式 SQL 数据库。您可以在此处了解更多关于 AWS Lightsail PostgreSQL 的信息:https://aws.amazon.com/lightsail/features/databases/,以及在此处了解关于 CockroachDB 的信息:https://www.cockroachlabs.com/

演讲者笔记:

我们将讨论为应用程序配置数据库的过程,并探索可用的不同选项。

部署:
工具:

为了将我们的应用程序部署到虚拟机,我们将使用 SSH 和 SCP。SSH (Secure Shell) 是一种安全网络协议,允许两个系统之间进行加密通信。SCP (Secure Copy) 是一个用于在两个系统之间安全传输文件的命令行工具。您可以在此处了解更多关于 SSH 的信息:https://www.ssh.com/ssh/,以及在此处了解关于 SCP 的信息:https://linuxize.com/post/how-to-use-scp-command-to-securely-transfer-files/

演讲者笔记:

我们的演讲者将引导我们完成将应用程序部署到虚拟机的过程,并解释自动化在部署中的重要性。

负载均衡器:
工具:

为了确保我们应用程序的可靠性和可扩展性,我们将使用 NGINX 作为我们的负载均衡器。NGINX 是一个流行的开源 Web 服务器和反向代理,以其高性能和可扩展性而闻名。您可以在此处了解更多关于 NGINX 的信息:https://www.nginx.com/

演讲者笔记:

我们将讨论负载均衡对 Web 应用程序的重要性,并逐步介绍为应用程序设置负载均衡器的过程。

自定义域名:
工具:

我们将使用 AWS Lightsail 为我们的应用程序设置自定义域名。自定义域名为您的 Web 应用程序提供了更专业和品牌化的 URL,并可以改善用户体验。您可以在此处了解更多关于使用 AWS Lightsail 设置自定义域名的信息:https://aws.amazon.com/lightsail/features/dns/

演讲者笔记:

我们的演讲者将引导我们完成为应用程序设置自定义域名的过程,解释品牌和用户体验的重要性。

崩溃恢复能力:
工具:

我们将使用 Supervisord 来确保我们应用程序的崩溃恢复能力。Supervisord 是一个客户端/服务器系统,允许在类 Unix 操作系统上控制和监控进程。您可以在此处了解更多关于 Supervisord 的信息:http://supervisord.org/

演讲者笔记:

我们将讨论 Web 应用程序崩溃恢复能力的重要性,并探索如何使用 DevOps 实践来实现它。

日志记录与监控:
工具:

对于我们的日志记录和监控需求,我们将使用 Django Logging 和 Supervisord UI。Django Logging 是 Django Web 框架的内置日志系统,为记录应用程序中的事件提供了一种灵活且可配置的方式。Supervisord UI 是一个基于 Web 的界面,用于管理和监控由 Supervisord 控制的进程。您可以在此处了解更多关于 Django Logging 的信息:https://docs.djangoproject.com/en/3.2/topics/logging/,以及在此处了解关于 Supervisord UI 的信息:https://github.com/Supervisor/supervisor/blob/master/docs/webui.rst

演讲者笔记:

我们的演讲者将讨论 Web 应用程序日志记录和监控的重要性,并逐步介绍为应用程序设置日志记录和监控的过程。

新需求带来的更新:
工具:

我们将使用 SCP 和 Django 迁移来根据新需求更新我们的应用程序。SCP (Secure Copy) 是一个用于在两个系统之间安全传输文件的命令行工具,而 Django 迁移提供了一种随着应用程序发展更新数据库架构的方法。您可以在此处了解更多关于 Django 迁移的信息:https://docs.djangoproject.com/en/3.2/topics/migrations/,以及在此处了解关于 SCP 的信息:https://linuxize.com/post/how-to-use-scp-command-to-securely-transfer-files/

演讲者笔记:

我们将讨论根据新需求更新应用程序的过程,并解释 DevOps 实践如何使此过程更简单、更高效。

生产环境中的数据库迁移:
工具:

对于我们在生产环境中的数据库迁移,我们将根据所使用的设置,使用带有 sqlite3 和 PostgreSQL 驱动程序的 Django 数据库迁移。这将允许我们在不丢失数据的情况下进行数据库架构更改。您可以在此处了解更多关于 Django 数据库迁移的信息:https://docs.djangoproject.com/en/3.2/topics/migrations/

演讲者笔记:

我们的演讲者将讨论在生产环境中迁移数据库的过程,并探索如何使用 DevOps 实践来实现数据库迁移。

安全性/模糊测试:
工具:

为了确保我们应用程序的安全性,我们将使用 PythonFuzz 进行安全测试和模糊测试。PythonFuzz 是一个基于 Python 的模糊测试工具,旨在查找代码中的错误和漏洞。您可以在此处了解更多关于 PythonFuzz 的信息:https://github.com/python-security/pyfuzz

演讲者笔记:

我们的演讲者将讨论 Web 应用程序安全测试和模糊测试的重要性,并逐步介绍使用 DevOps 实践实施安全测试和模糊测试的过程。

备份/恢复程序:
工具:

为了确保我们应用程序的可靠性和可用性,我们将使用 Django Database Backup 来设置备份和恢复程序。Django Database Backup 是一个 Django 扩展,提供了一种备份和恢复数据库的简单方法。您可以在此处了解更多关于 Django Database Backup 的信息:https://django-dbbackup.readthedocs.io/en/stable/

演讲者笔记:

我们将讨论 Web 应用程序备份和恢复程序的重要性,并逐步介绍使用 DevOps 实践设置和测试备份和恢复程序的过程。

法语

Webapp :

演讲者笔记 :

我们的演讲者将介绍我们将要构建和部署的 Web 应用程序,解释其目的以及与 DevOps 工作流程的相关性。

构建与测试 :

演讲者笔记 :

我们将逐步介绍构建和测试应用程序的过程,强调测试的重要性以及它如何融入 DevOps 工作流程。

虚拟机配置 :

演讲者笔记 :

我们的演讲者将讨论为托管应用程序配置虚拟机的过程,解释可用的不同选项以及如何为您的需求选择最佳选项。

数据库配置 :

演讲者笔记 :

我们将讨论为应用程序配置数据库的过程,并探索可用的不同选项。

部署 :

演讲者笔记 :

我们的演讲者将引导我们完成将应用程序部署到虚拟机的过程,并解释自动化在部署中的重要性。

负载均衡器 :

演讲者笔记 :

我们将讨论负载均衡对 Web 应用程序的重要性,并逐步介绍为应用程序设置负载均衡器的过程。

自定义域名 :

演讲者笔记 :

我们的演讲者将引导我们完成为应用程序设置自定义域名的过程,解释品牌和用户体验的重要性。

崩溃恢复能力 :

演讲者笔记 :

我们将讨论 Web 应用程序崩溃恢复能力的重要性,并探索如何使用 DevOps 实践来实现它。

日志记录与监控 :

演讲者笔记 :

我们的演讲者将讨论 Web 应用程序日志记录和监控的重要性,并逐步介绍为应用程序设置日志记录和监控的过程。

新需求带来的更新 :

演讲者笔记 :

我们将讨论根据新需求更新应用程序的过程,并解释 DevOps 实践如何使此过程更简单、更高效。

生产环境中的数据库迁移 :

演讲者笔记 :

我们的演讲者将讨论在生产环境中迁移数据库的过程,并探索如何使用 DevOps 实践来实现数据库迁移。

安全性/模糊测试 :

演讲者笔记 :

我们的演讲者将讨论 Web 应用程序安全测试和模糊测试的重要性,并逐步介绍使用 DevOps 实践实施安全测试和模糊测试的过程。

备份/恢复程序 :

演讲者笔记 :

我们将讨论 Web 应用程序备份和恢复程序的重要性,并逐步介绍使用 DevOps 实践设置和测试备份和恢复程序的过程。