YAML部署实践

参考文档

LibYAML

LibYAML涵盖了演示和解析过程。 因此,LibYAML定义了以下两个处理器:
- 解析器,其接收字节的输入流并产生解析事件序列。
- 发射器,它接收一系列事件并产生一串字节。

The processes of parsing and presenting are inverse to each other. Any sequence of events produced by parsing a well-formed YAML document should be acceptable by the Emitter, which should produce an equivalent document. Similarly, any document produced by emitting a sequence of events should be acceptable for the Parser, which should produce an equivalent sequence of events.

解析和演示的过程彼此相反。 通过分析格式良好的YAML文档所产生的任何事件序列应由发射器接受,该发射器应该产生等效的文件。 类似地,通过发出一系列事件而产生的任何文档应该被解析器所接收,该解析器应该产生等效的事件序列。

Created with Raphaël 2.1.0 YAML Document [INPUT] 字节流 (an input stream of bytes) Parser 事件(Any sequence of events) Emitter [OUTPUT]字节流 (an input stream of bytes) YAML Document

事件类型

STREAM-START
STREAM-END
DOCUMENT-START
DOCUMENT-END
ALIAS
SCALAR
SEQUENCE-START
SEQUENCE-END
MAPPING-START
MAPPING-END

Yaml-cpp Example

#include "yaml.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>    

// our data models
struct Vec3
{   
   float x, y, z;
};  

struct Power
{
   std::string name;
   int damage;
}; 

struct Monster 
{   
    std::string name;
    Vec3 position;
    std::vector <Power> powers;
};  

// operators for parsing
void operator >> (const YAML::Node& node, Vec3& v)
{   
   node[0] >> v.x;
   node[1] >> v.y;
   node[2] >> v.z;
}

void operator >> (const YAML::Node& node, Power& power)
{   
   node["name"] >> power.name;
   node["damage"] >> power.damage;
}   

void operator >> (const YAML::Node& node, Monster& monster)
{       
    node["name"] >> monster.name;
    node["position"] >> monster.position;
    const YAML::Node& powers = node["powers"];
    for(unsigned i = 0; i < powers.size(); i++)
    {
        Power power;
        powers[i] >> power;
        monster.powers.push_back(power);
    }   
}   

// operators for emitting
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v)
{   
    out << YAML::Flow;
    out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
    return out;
}

YAML::Emitter& operator << (YAML::Emitter& out, const Power& power) 
{
    out << YAML::BeginMap;
    out << YAML::Key << "name";
    out << YAML::Value << power.name;
    out << YAML::Key << "damage";
    out << YAML::Value << power.damage;
    out << YAML::EndMap;
    return out;
}

YAML::Emitter& operator << (YAML::Emitter& out, const Monster& monster) 
{
    out << YAML::BeginMap;
    out << YAML::Key << "name";
    out << YAML::Value << monster.name;
    out << YAML::Key << "position";
    out << YAML::Value << monster.position;
    out << YAML::Key << "powers";
    out << YAML::Value;
    out << YAML::BeginSeq;
    for(size_t pidx = 0; pidx < monster.powers.size(); ++pidx)
    {
        out << monster.powers[pidx];
    }
    out << YAML::EndSeq;
    out << YAML::EndMap;
    return out;
}


int main()
{
   std::string monsters_yaml("- name: Ogre\n  position: [0, 5, 0]\n  powers:\n    - name: Club\n      damage: 10\n    - name: Fist\n      damage: 8\n- name: Dragon\n  position: [1, 0, 10]\n  powers:\n    - name: Fire Breath\n      damage: 25\n    - name: Claws\n      damage: 15\n- name: Wizard\n  position: [5, -3, 0]\n  powers:\n    - name: Acid Rain\n      damage: 50\n    - name: Staff\n      damage: 3\n");

    // list of monsters
    std::vector<Monster> monsters;

    // write out the monster.yaml 
    std::ofstream monsters_yaml_file;
    monsters_yaml_file.open("monsters.yaml");
    monsters_yaml_file << monsters_yaml;
    monsters_yaml_file.close();

    // read in the the monster.yaml 
    std::ifstream fin("monsters.yaml");
    YAML::Parser parser(fin);
    YAML::Node doc;
    parser.GetNextDocument(doc);
    for(size_t i = 0; i < doc.size(); i++)
    {
        Monster monster;
        doc[i] >> monster;
        monsters.push_back(monster);
        std::cout << monster.name << std::endl;
    }

    YAML::Emitter out;
    //out << YAML::BeginSeq;
    //for(size_t i = 0; i < monsters.size(); i++)
    //{
    //    out << monsters[i];
    //}
    //out << YAML::EndSeq;

    out << monsters; //stlemitter.h template interface 

    std::cout << out.c_str() << std::endl;
    return 0;
}

YAML文档补充翻译

YAML represents type information of native data structures with a simple identifier, called a tag. Global tags are URIs( Uniform Resource Identifiers (URI)) and hence globally unique across all applications. The “tag:” URI scheme is recommended for all global YAML tags. In contrast, local tags are specific to a single application. Local tags start with “!”, are not URIs and are not expected to be globally unique. YAML provides a “TAG” directive to make tag notation less verbose; it also offers easy migration from local to global tags. To ensure this, local tags are restricted to the URI character set and use URI character escaping.

YAML利用称为标签的简单标识符来表示本地数据结构的类型信息。 全局标记是URI,因此在所有应用程序中都是全局唯一的。 对于所有全局YAML标签,建议使用“tag:”URI方案。 相反,本地标签特定于单个应用程序。 本地标签以“!”开始,不是URI,并不是全局唯一的。 YAML提供了一个“TAG”指令,使标签符号不冗余; 它还提供从本地到全局标签的轻松迁移。 为了确保这一点,本地标签仅限于URI字符集,并使用URI字符转义。

YAML does not mandate any special relationship between different tags that begin with the same substring. Tags ending with URI fragments (containing “#”) are no exception; tags that share the same base URI but differ in their fragment part are considered to be different, independent tags. By convention, fragments are used to identify different “variants” of a tag, while “/” is used to define nested tag “namespace” hierarchies. However, this is merely a convention, and each tag may employ its own rules. For example, Perl tags may use “::” to express namespace hierarchies, Java tags may use “.”, etc.

YAML不要求以相同的子字符串开头的不同标签之间的任何特殊关系。 以URI片段结尾的标签(包含“#”)也不例外; 共享相同基本URI但在片段部分不同的标签被认为是不同的独立标签。 按照惯例,片段用于标识标签的不同“变体”,而“/”用于定义嵌套标签“命名空间”层次结构。 然而,这仅仅是一个惯例,每个标签都可以使用自己的规则。 例如,Perl标签可能使用“::”来表示命名空间层次结构,Java标签可能使用“。”等。

YAML tags are used to associate meta information with each node. In particular, each tag must specify the expected node kind (scalar, sequence, or mapping). Scalar tags must also provide a mechanism for converting formatted content to a canonical form for supporting equality testing. Furthermore, a tag may provide additional information such as the set of allowed content values for validation, a mechanism for tag resolution, or any other data that is applicable to all of the tag’s nodes.

YAML标签用于将元信息与每个节点相关联。 特别地,每个标签必须指定预期的节点种类(标量,序列或映射)。 标量标签还必须提供将格式化内容转换为规范表单以支持相似性测试的机制。 此外,标签可以提供附加信息,例如用于验证的允许内容值集合,标签解析机制或适用于所有标签节点的任何其他数据。

未完待续

### 使用 YAML 文件在 Kubernetes 中部署应用程序的最佳实践 #### 创建 Deployment 的 YAML 文件 为了在 Kubernetes 集群中部署一个应用程序,可以编写一个 YAML 文件定义所需的资源对象。以下是一个典型的 Deployment YAML 文件结构: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-app-deployment spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: nginx:latest ports: - containerPort: 80 ``` 上述文件描述了一个名为 `my-app-deployment` 的 Deployment 对象[^2]。它指定了三个副本 (`replicas: 3`) 并使用 Nginx 容器镜像作为基础。 #### 创建 Service 的 YAML 文件 为了让外部能够访问该 Deployment 所管理的 Pod,还需要创建一个 Service 资源对象。以下是对应的 YAML 文件示例: ```yaml apiVersion: v1 kind: Service metadata: name: my-app-service spec: type: NodePort selector: app: my-app ports: - protocol: TCP port: 80 targetPort: 80 nodePort: 30007 ``` 此配置中的 `Service` 类型设置为 `NodePort`,允许通过节点 IP 和指定端口(如 `30007`)访问服务。 #### 应用 YAML 文件并验证状态 完成 YAML 文件后,可以通过以下命令将其应用于集群: ```bash kubectl apply -f deployment.yaml kubectl apply -f service.yaml ``` 随后可执行以下命令确认资源已成功启动: ```bash kubectl get deployments kubectl get pods kubectl get svc ``` 如果一切正常,则可通过浏览器或 curl 访问暴露的服务地址:`http://<NodeIP>:30007`。 #### 自动化部署与扩展的应用场景 对于更复杂的生产环境需求,建议采用 CI/CD 流程实现自动化的构建、测试以及发布流程。这不仅提高了开发效率,还减少了人为错误的可能性[^3]。具体而言,在实际项目中可能涉及以下几个方面的工作内容: - **持续集成**:定期拉取最新代码版本至流水线,并触发单元测试或其他质量保障措施; - **弹性伸缩策略**:依据实时负载情况动态调整实例数量以优化性能表现及成本控制; - **容器编排平台支持**:利用 Helm Chart 或其他高级工具简化复杂多组件系统的安装过程。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值