技术文档收录
ASCII
Tcpdump
IPV4保留地址段
深入理解以太网网线原理 - 三帛的世界
Linux
WireGuard 一键安装脚本 | 秋水逸冰
SSH Config 那些你所知道和不知道的事 | Deepzz's Blog
Linux 让终端走代理的几种方法
ubuntu 20.04 server 版设置静态 IP 地址 - 链滴
Linux 挂载 Windows 共享磁盘的方法 - 技术学堂
将 SMB/CIFS 网络硬盘永久的挂载到 Ubuntu 上 - 简书
linux 获取当前脚本的绝对路径 | aimuke
[Linux] Linux 使用 / dev/urandom 生成随机数 - piaohua's blog
Linux 生成随机数的多种方法 | Just Do It
Linux 的 Centos7 版本下忘记 root 或者普通用户密码怎么办?
Git 强制拉取覆盖本地
SSH 安全加固指南 - FreeBuf 网络安全行业门户
Linux 系统安全强化指南 - FreeBuf 网络安全行业门户
Linux 入侵排查 - FreeBuf 网络安全行业门户
sshd_config 配置详解 - 简书
SSH 权限详解 - SegmentFault 思否
CentOS 安装 node.js 环境 - SegmentFault 思否
如何在 CentOS 7 上安装 Node.js 和 npm | myfreax
几款 ping tcping 工具总结
OpenVpn 搭建教程 | Jesse's home
openvpn 一键安装脚本 - 那片云
OpenVPN 解决 每小时断线一次 - 爱开源
OpenVPN 路由设置 – 凤曦的小窝
OpenVPN 设置非全局代理 - 镜子的记录簿
TinyProxy 使用帮助 - 简书
Ubuntu 下使用 TinyProxy 搭建代理 HTTP 服务器_Linux_运维开发网_运维开发技术经验分享
Linux 软件包管理工具 Snap 常用命令 - 简书
linux systemd 参数详解
Systemd 入门教程:命令篇 - 阮一峰的网络日志
记一次 Linux 木马清除过程
rtty:在任何地方通过 Web 访问您的终端
02 . Ansible 高级用法 (运维开发篇)
终于搞懂了服务器为啥产生大量的 TIME_WAIT!
巧妙的 Linux 命令,再来 6 个!
77% 的 Linux 运维都不懂的内核问题,这篇全告诉你了
运维工程师必备:请收好 Linux 网络命令集锦
一份阿里员工的 Java 问题排查工具单
肝了 15000 字性能调优系列专题(JVM、MySQL、Nginx and Tomcat),看不完先收
作业调度算法(FCFS,SJF,优先级调度,时间片轮转,多级反馈队列) | The Blog Of WaiterXiaoYY
看了这篇还不会 Linux 性能分析和优化,你来打我
2019 运维技能风向标
更安全的 rm 命令,保护重要数据
求你了,别再纠结线程池大小了!
Linux sudo 详解 | 失落的乐章
重启大法好!线上常见问题排查手册
sudo 使用 - 笨鸟教程的博客 | BY BenderFly
shell 在手分析服务器日志不愁? - SegmentFault 思否
sudo 与 visudo 的超细用法说明_陈发哥 007 的技术博客_51CTO 博客
ESXI 下无损扩展 Linux 硬盘空间 | Naonao Blog
Linux 学习记录:su 和 sudo | Juntao Tan 的个人博客
使用者身份切换 | Linux 系统教程(笔记)
你会使用 Linux 编辑器 vim 吗?
在 Windows、Linux 和 Mac 上查看 Wi-Fi 密码
linux 隐藏你的 crontab 后门 - 简书
Linux 定时任务详解 - Tr0y's Blog
linux 的 TCP 连接数量最大不能超过 65535 个吗,那服务器是如何应对百万千万的并发的?_一口 Linux 的博客 - CSDN 博客_tcp 连接数多少正常
万字长文 + 28 张图,一次性说清楚 TCP,运维必藏
为什么 p2p 模式的 tunnel 底层通常用 udp 而不是 tcp?
记一次服务器被入侵挖矿 - tlanyan
shell 判断一个变量是否为空方法总结 - 腾讯云开发者社区 - 腾讯云
系统安装包管理工具 | Escape
编译代码时动态地链接库 - 51CTO.COM
甲骨文 Oracle Cloud 添加新端口开放的方法 - WirelessLink 社区
腾讯云 Ubuntu 添加 swap 分区的方法_弓弧名家_玄真君的博客 - CSDN 博客
Oracle 开放全部端口并关闭防火墙 - 清~ 幽殇
谁再说不熟悉 Linux 命令, 就把这个给他扔过去!
即插即用,运维工程师必会正则表达式大全
Shell脚本编写及常见面试题
Samba 文件共享服务器
到底一台服务器上最多能创建多少个 TCP 连接 | plantegg
SSH 密钥登录 - SSH 教程 - 网道
在 Bash 中进行 encodeURIComponent/decodeURIComponent | Harttle Land
使用 Shell 脚本来处理 JSON - Tom CzHen's Blog
Docker
「Docker」 - 保存镜像 - 知乎
终于可以像使用 Docker 一样丝滑地使用 Containerd 了!
私有镜像仓库选型:Harbor VS Quay - 乐金明的博客 | Robin Blog
exec 与 entrypoint 使用脚本 | Mr.Cheng
Dockerfile 中的 CMD 与 ENTRYPOINT
使用 Docker 配置 MySQL 主从数据库 - 墨天轮
Alpine vs Distroless vs Busybox – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang | 云原生
再见,Docker!
docker save 与 docker export 的区别 - jingsam
如何优雅的关闭容器
docker 储存之 tmpfs 、bind-mounts、volume | 陌小路的个人博客
Dockerfile 中 VOLUME 与 docker -v 的区别是什么 - 开发技术 - 亿速云
理解 docker 容器的退出码 | Vermouth | 博客 | docker | k8s | python | go | 开发
【Docker 那些事儿】容器监控系统,来自 Docker 的暴击_飞向星的客机的博客 - CSDN 博客
【云原生】Docker 镜像详细讲解_微枫 Micromaple 的博客 - CSDN 博客_registry-mirrors
【云原生】Helm 架构和基础语法详解
CMD 和 Entrypoint 命令使用变量的用法
实时查看容器日志 - 苏洋博客
Traefik 2 使用指南,愉悦的开发体验 - 苏洋博客
为你的 Python 应用选择一个最好的 Docker 映像 | 亚马逊 AWS 官方博客
【云原生】镜像构建实战操作(Dockerfile)
Docker Compose 中的 links 和 depends_on 的区别 - 编程知识 - 白鹭情
Python
Pipenv:新一代Python项目环境与依赖管理工具 - 知乎
Python list 列表实现栈和队列
Python 各种排序 | Lesley's blog
Python 中使用 dateutil 模块解析时间 - SegmentFault 思否
一个小破网站,居然比 Python 官网还牛逼
Python 打包 exe 的王炸 - Nuitka
Django - - 基础 - - Django ORM 常用查询语法及进阶
[Python] 小知識:== 和 is 的差異 - Clay-Technology World
Window
批处理中分割字符串 | 网络进行时
Windows 批处理基础命令学习 - 简书
在Windows上设置WireGuard
Windows LTSC、LTSB、Server 安装 Windows Store 应用商店
windows 重启 rdpclip.exe 的脚本
中间件
Nginx 中的 Rewrite 的重定向配置与实践
RabbitMQ 的监控
RabbitMq 最全的性能调优笔记 - SegmentFault 思否
为什么不建议生产用 Redis 主从模式?
高性能消息中间件——NATS
详解:Nginx 反代实现 Kibana 登录认证功能
分布式系统关注点:仅需这一篇,吃透 “负载均衡” 妥妥的
仅需这一篇,妥妥的吃透” 负载均衡”
基于 nginx 实现上游服务器动态自动上下线——不需 reload
Nginx 学习书单整理
最常见的日志收集架构(ELK Stack)
分布式之 elk 日志架构的演进
CAT 3.0 开源发布,支持多语言客户端及多项性能提升
Kafka 如何做到 1 秒处理 1500 万条消息?
Grafana 与 Kibana
ELK 日志系统之通用应用程序日志接入方案
ELK 简易 Nginx 日志系统搭建: ElasticSearch+Kibana+Filebeat
记一次 Redis 连接池问题引发的 RST
把 Redis 当作队列来用,你好大的胆子……
Redis 最佳实践:业务层面和运维层面优化
Redis 为什么变慢了?常见延迟问题定位与分析
好饭不怕晚,扒一下 Redis 配置文件的底 Ku
rabbitmq 集群搭建以及万级并发下的性能调优
别再问我 Redis 内存满了该怎么办了
Nginx 状态监控及日志分析
uWSGI 的安装及配置详解
uwsgi 异常服务器内存 cpu 爆满优化思路
Uwsgi 内存占用过多 - 简书
Nginx 的 limit 模块
Nginx 内置模块简介
Redis 忽然变慢了如何排查并解决?_redis_码哥字节_InfoQ 写作社区
领导:谁再用 redis 过期监听实现关闭订单,立马滚蛋!
Nginx 限制 IP 访问频率以及白名单配置_问轩博客
Nginx $remote_addr 和 $proxy_add_x_forwarded_for 变量详解
Caddy 部署实践
一文搞定 Nginx 限流
数据库
SqlServer 将数据库中的表复制到另一个数据库_MsSql_脚本之家
SQL Server 数据库同步,订阅、发布、复制、跨服务器
sql server 无法删除本地发布 | 辉克's Blog
SQLite全文检索
SQL 重复记录查询的几种方法 - 简书
SQL SERVER 使用订阅发布同步数据库(转)
Mysql 查看用户连接数配置及每个 IP 的请求情况 - 墨天轮
优化 SQL 的 21 条方案
SQL Server 连接时好时坏的奇怪问题
MS SQL 执行大脚本文件时,提示 “内存不足” 的解决办法 - 阿里云开发者社区
防火墙-iptables
iptables 常用规则:屏蔽 IP 地址、禁用 ping、协议设置、NAT 与转发、负载平衡、自定义链
防火墙 iptables 企业防火墙之 iptables
Linux 防火墙 ufw 简介
在 Ubuntu 中用 UFW 配置防火墙
在 Ubuntu20.04 上怎样使用 UFW 配置防火墙 - 技术库存网
监控类
开箱即用的 Prometheus 告警规则集
prometheus☞搭建 | zyh
docker 部署 Prometheus 监控服务器及容器并发送告警 | chris'wang
PromQL 常用命令 | LRF 成长记
prometheus 中使用 python 手写 webhook 完成告警
持续集成CI/CD
GitHub Actions 的应用场景 | 记录干杯
GithubActions · Mr.li's Blog
工具类
GitHub 中的开源网络广告杀手,十分钟快速提升网络性能
SSH-Auditor:一款 SHH 弱密码探测工具
别再找了,Github 热门开源富文本编辑器,最实用的都在这里了 - srcmini
我最喜欢的 CLI 工具
推荐几款 Redis 可视化工具
内网代理工具与检测方法研究
环境篇:数据同步工具 DataX
全能系统监控工具 dstat
常用 Web 安全扫描工具合集
给你一款利器!轻松生成 Nginx 配置文件
教程类
Centos7 搭建神器 openvpn | 运维随笔
搭建 umami 收集个人网站统计数据 | Reorx’s Forge
openvpn安装教程
基于 gitea+drone 完成小团队的 CI/CD - 德国粗茶淡饭
将颜色应用于交替行或列
VMware Workstation 全系列合集 精简安装注册版 支持 SLIC2.6、MSDM、OSX 更新 16.2.3_虚拟机讨论区_安全区 卡饭论坛 - 互助分享 - 大气谦和!
在 OpenVPN 上启用 AD+Google Authenticator 认证 | 运维烂笔头
Github 进行 fork 后如何与原仓库同步:重新 fork 很省事,但不如反复练习版本合并 · Issue #67 · selfteaching/the-craft-of-selfteaching
卧槽,VPN 又断开了!!- 阿里云开发者社区
Grafana Loki 学习之踩坑记
zerotier 的 planet 服务器(根服务器)的搭建踩坑记。无需 zerotier 官网账号。
阿里云 qcow2 镜像转 vmdk,导入 ESXi - 唐际忠的博客
Caddy 入门 – 又见杜梨树
【Caddy2】最新 Caddy2 配置文件解析 - Billyme 的博客
Web 服务器 Caddy 2 | Haven200
手把手教你打造高效的 Kubernetes 命令行终端
Keras 作者:给软件开发者的 33 条黄金法则
超详细的网络抓包神器 Tcpdump 使用指南
使用 fail2ban 和 FirewallD 黑名单保护你的系统
linux 下 mysql 数据库单向同步配置方法分享 (Mysql)
MySQL 快速删除大量数据(千万级别)的几种实践方案
GitHub 上的优质 Linux 开源项目,真滴牛逼!
WireGuard 教程:使用 Netmaker 来管理 WireGuard 的配置 – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang | 云原生
Tailscale 基础教程:Headscale 的部署方法和使用教程 – 云原生实验室 - Kubernetes|Docker|Istio|Envoy|Hugo|Golang | 云原生
Nebula Graph 的 Ansible 实践
改进你的 Ansible 剧本的 4 行代码
Caddy 2 快速简单安装配置教程 – 高玩梁的博客
切换至 Caddy2 | 某不科学的博客
Caddy2 简明教程 - bleem
树莓派安装 OpenWrt 突破校园网限制 | Asttear's Blog
OpenVPN 路由设置 – 凤曦的小窝
个性化编译 LEDE 固件
盘点各种 Windows/Office 激活工具
[VirtualBox] 1、NAT 模式下端口映射
VirtualBox 虚拟机安装 openwrt 供本机使用
NUC 折腾笔记 - 安装 ESXi 7 - 苏洋博客
锐捷、赛尔认证 MentoHUST - Ubuntu 中文
How Do I Use A Client Certificate And Private Key From The IOS Keychain? | OpenVPN
比特记事簿: 笔记: 使用电信 TR069 内网架设 WireGuard 隧道异地组网
利用 GitHub API 获取最新 Releases 的版本号 | 这是只兔子
docsify - 生成文档网站简单使用教程 - SegmentFault 思否
【干货】Chrome 插件 (扩展) 开发全攻略 - 好记的博客
一看就会的 GitHub 骚操作,让你看上去像一位开源大佬
【计算机网络】了解内网、外网、宽带、带宽、流量、网速_墩墩分墩 - CSDN 博客
mac-ssh 配置 | Sail
如何科学管理你的密码
VirtualBox NAT 端口映射实现宿主机与虚拟机相互通信 | Shao Guoliang 的博客
CentOS7 配置网卡为静态 IP,如果你还学不会那真的没有办法了!
laisky-blog: 近期折腾 tailscale 的一些心得
使用 acme.sh 给 Nginx 安装 Let’ s Encrypt 提供的免费 SSL 证书 · Ruby China
acme 申请 Let’s Encrypt 泛域名 SSL 证书
从 nginx 迁移到 caddy
使用 Caddy 替代 Nginx,全站升级 https,配置更加简单 - Diamond-Blog
http.proxy - Caddy 中文文档
动手撸个 Caddy(二)| Caddy 命令行参数最全教程 | 飞雪无情的总结
Caddy | 学习笔记 - ijayer
Caddy 代理 SpringBoot Fatjar 应用上传静态资源
使用 graylog3.0 收集 open××× 日志进行审计_年轻人,少吐槽,多搬砖的技术博客_51CTO 博客
提高国内访问 github 速度的 9 种方法! - SegmentFault 思否
VM16 安装 macOS 全网最详细
2022 目前三种有效加速国内 Github
How to install MariaDB on Alpine Linux | LibreByte
局域网内电脑 - ipad 文件共享的三种方法 | 岚
多机共享键鼠软件横向测评 - 尚弟的小笔记
VLOG | ESXI 如何升级到最新版,无论是 6.5 还是 6.7 版本都可以顺滑升级。 – Vedio Talk - VLOG、科技、生活、乐分享
远程修改 ESXi 6.7 管理 IP 地址 - 腾讯云开发者社区 - 腾讯云
几乎不要钱自制远程 PLC 路由器方案
traefik 简易入门 | 个人服务器运维指南 | 山月行
更完善的 Docker + Traefik 使用方案 - 苏洋博客
MicroSD·TF 卡终极探秘 ·MLC 颗粒之谜 1 三星篇_microSD 存储卡_什么值得买
macOS 绕过公证和应用签名方法 - 走客
MiscSecNotes / 内网端口转发及穿透. md at master · JnuSimba/MiscSecNotes
我有特别的 DNS 配置和使用技巧 | Sukka's Blog
SEO:初学者完整指南
通过 OpenVPN 实现流量审计
OpenVPN-HOWTO
OpenVPN Server · Devops Roadmap
Linux 运维必备的 13 款实用工具, 拿好了~
linux 平台下 Tomcat 的安装与优化
Linux 运维跳槽必备的 40 道面试精华题
Bash 脚本进阶,经典用法及其案例 - alonghub - 博客园
推荐几个非常不错的富文本编辑器 - 走看看
在 JS 文件中加载 JS 文件的方法 - 月光博客
#JavaScript 根据需要动态加载脚本并设置自定义参数
笔记本电脑 BIOS 修改及刷写教程
跨平台加密 DNS 和广告过滤 personalDNSfilter · LinuxTOY
AdGuard Home 安装及使用指北
通过 Amazon S3 协议挂载 OSS
记一次云主机如何挂载对象存储
本文档发布于https://mrdoc.fun
-
+
首页
【云原生】Helm 架构和基础语法详解
> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [www.cnblogs.com](https://www.cnblogs.com/liugp/p/16659802.html) 目录 * [一、概述](#一概述) * [二、Helm 架构](#二helm-架构) * [三、Helm 安装](#三helm-安装) * [四、Helm 组件及相关术语](#四helm-组件及相关术语) * [五、Helm Chart 详解](#五helm-chart-详解) * [1)Chart 目录结构](#1chart-目录结构) * [2)Chart.yaml 文件](#2chartyaml-文件) * [3)Chart 依赖管理(dependencies)](#3chart-依赖管理dependencies) * [4)通过依赖导入子 Value](#4通过依赖导入子value) * [六、Templates and Values](#六templates-and-values) * [1)Templates and Values 简介](#1templates-and-values-简介) * [2)预定义的 Values](#2预定义的-values) * [3)范围,依赖和值](#3范围依赖和值) * [4)全局 Values](#4全局values) * [七、Helm 资源安装顺序](#七helm-资源安装顺序) * [八、Helm 安装 Chart 包的三种方式](#八helm-安装-chart-包的三种方式) * [1)values 传参](#1values-传参) * [2)【第一种方式】直接在线 安装不需要先下载包到本地](#2第一种方式直接在线-安装不需要先下载包到本地) * [3)【第二种方式】离线安装 直接通过安装包安装](#3第二种方式离线安装-直接通过安装包安装) * [4)【第三种方式】离线安装 解压包再安装](#4第三种方式离线安装-解压包再安装) * [九、Helm 基础语法](#九helm-基础语法) * [1)变量](#1变量) * [2)内置对象](#2内置对象) * [3)常用的内置函数](#3常用的内置函数) * [1、quote and squote](#1quote-and-squote) * [2、default](#2default) * [3、print](#3print) * [4、println](#4println) * [5、printf](#5printf) * [6、trim](#6trim) * [7、trimAll](#7trimall) * [8、lower](#8lower) * [9、upper](#9upper) * [10、title](#10title) * [11、substr](#11substr) * [12、abbrev](#12abbrev) * [13、contains](#13contains) * [14、cat](#14cat) * [15、indent](#15indent) * [16、nindent](#16nindent) * [17、replace](#17replace) * [18、date](#18date) * [4)类型转换函数](#4类型转换函数) * [5)正则表达式(Regular Expressions)](#5正则表达式regular-expressions) * [6)编码和解码函数](#6编码和解码函数) * [7)Dictionaries and Dict Functions](#7dictionaries-and-dict-functions) * [1、创建字典(dict)](#1创建字典dict) * [2、获取值(get)](#2获取值get) * [3、添加键值对(set)](#3添加键值对set) * [4、删除(unset)](#4删除unset) * [5、判断 key(hasKey)](#5判断keyhaskey) * [6、pluck](#6pluck) * [7、合并 dict(merge, mustMerge)](#7合并-dictmerge-mustmerge) * [8、获取所有 keys](#8获取所有-keys) * [9、获取所有 values](#9获取所有-values) * [8)Lists and List Functions](#8lists-and-list-functions) * [1、创建列表](#1创建列表) * [2、获取列表第一项(first, mustFirst)](#2获取列表第一项first-mustfirst) * [3、获取列表的尾部内容(rest, mustRest)](#3获取列表的尾部内容rest-mustrest) * [4、获取列表的最后一项(last, mustLast)](#4获取列表的最后一项last-mustlast) * [5、获取列表所有内容(initial, mustInitial)](#5获取列表所有内容initial-mustinitial) * [6、末尾添加元素(append, mustAppend)](#6末尾添加元素append-mustappend) * [7、前面添加元素(prepend, mustPrepend)](#7前面添加元素prepend-mustprepend) * [8、多列表连接(concat)](#8多列表连接concat) * [9、反转(reverse, mustReverse)](#9反转reverse-mustreverse) * [10、去重(uniq, mustUniq)](#10去重uniq-mustuniq) * [11、过滤(without, mustWithout)](#11过滤without-mustwithout) * [12、判断元素是否存在(has, mustHas)](#12判断元素是否存在has-musthas) * [13、删除空项(compact, mustCompact)](#13删除空项compact-mustcompact) * [14、index](#14index) * [15、获取部分元素(slice, mustSlice)](#15获取部分元素slice-mustslice) * [16、构建一个整数列表(until)](#16构建一个整数列表until) * [17、seq](#17seq) * [9)数学函数(Math Functions)](#9数学函数math-functions) * [1、求和(add)](#1求和add) * [2、自加 1(add1)](#2自加1add1) * [3、相减(sub)](#3相减sub) * [4、除(div)](#4除div) * [5、取模(mod)](#5取模mod) * [6、相乘(mul)](#6相乘mul) * [7、获取最大值(max)](#7获取最大值max) * [8、获取最小值(min)](#8获取最小值min) * [9、获取长度(len)](#9获取长度len) * [10)Network Functions](#10network-functions) * [10)条件语句](#10条件语句) * [11)变更作用域 with](#11变更作用域-with) * [12)rang 循环语句](#12rang循环语句) * [13)命名模板](#13命名模板) * [1、用 define 和 template 声明和使用模板](#1用define和template声明和使用模板) * [2、设置模板范围](#2设置模板范围) * [3、include 方法](#3include-方法) * [14)NOTES.txt 文件](#14notestxt文件) * [15)模板调试](#15模板调试) 一、概述 ---- 我们可以将 Helm 看作 Kubernetes 下的 apt-get/yum。Helm 是 kubernetes 的包管理器,helm 仓库里面只有配置清单文件, 而没有镜像, 镜像还是由镜像仓库来提供, 比如 hub.docker.com、私有仓库。 官方文档:[https://v3.helm.sh/zh/docs/](https://v3.helm.sh/zh/docs/) 其实之前也写过关于 helm 的一篇文章【[Kubernetes(k8s)包管理器 Helm(Helm3)介绍 & Helm3 安装 Harbor](https://www.cnblogs.com/liugp/p/16440583.html)】,可能讲的不够细致,这里会更加细致的讲解 helm。 二、Helm 架构 --------- ![](https://img-blog.csdnimg.cn/260bc6ca81884a3bbb742bbb0c27303f.png) 三、Helm 安装 --------- 下载地址:[https://github.com/helm/helm/releases](https://github.com/helm/helm/releases) ``` # 下载包 $ wget https://get.helm.sh/helm-v3.9.4-linux-amd64.tar.gz # 解压压缩包 $ tar -xf helm-v3.9.4-linux-amd64.tar.gz # 制作软连接 $ ln -s /opt/helm/linux-amd64/helm /usr/local/bin/helm # 验证 $ helm version $ helm help ``` 四、Helm 组件及相关术语 -------------- * `Helm`——Helm 是一个命令行下的**客户端工具**。主要用于 Kubernetes 应用程序 Chart 的创建、打包、发布以及创建和管理本地和远程的 Chart 仓库。 * `Chart`——Chart 代表着 **Helm 包**。它包含在 Kubernetes 集群内部运行应用程序,工具或服务所需的所有资源定义。你可以把它看作是 Homebrew formula,Apt dpkg,或 Yum RPM 在 Kubernetes 中的等价物。 * `Release`——Release 是运行在 Kubernetes 集群中的 **chart 的实例**。一个 chart 通常可以在同一个集群中安装多次。每一次安装都会创建一个新的 release。 * `Repoistory`——Repository(**仓库**) 是用来存放和共享 charts 的地方。它就像 Perl 的 CPAN 档案库网络 或是 Fedora 的 软件包仓库,只不过它是供 Kubernetes 包所使用的。 五、Helm Chart 详解 --------------- ### 1)Chart 目录结构 ``` # 通过helm create命令创建一个新的chart包 helm create nginx tree nginx ``` ![](https://img-blog.csdnimg.cn/66362b56c2ec4d4b8bad9ccc30eebb8a.png) ``` nginx/ ├── charts #依赖其他包的charts文件 ├── Chart.yaml # 该chart的描述文件,包括ico地址,版本信息等 ├── templates # #存放k8s模板文件目录 │ ├── deployment.yaml # 创建k8s资源的yaml 模板 │ ├── _helpers.tpl # 下划线开头的文件,可以被其他模板引用 │ ├── hpa.yaml # 弹性扩缩容,配置服务资源CPU 内存 │ ├── ingress.yaml # ingress 配合service域名访问的配置 │ ├── NOTES.txt # 说明文件,helm install之后展示给用户看的内容 │ ├── serviceaccount.yaml # 服务账号配置 │ ├── service.yaml # kubernetes Serivce yaml 模板 │ └── tests # 测试模块 │ └── test-connection.yaml └── values.yaml # 给模板文件使用的变量 ``` 可能有写包还会有以下几个目录: ``` wordpress/ ... LICENSE # 可选: 包含chart许可证的纯文本文件 README.md # 可选: 可读的README文件 values.schema.json # 可选: 一个使用JSON结构的values.yaml文件 charts/ # 包含chart依赖的其他chart crds/ # 自定义资源的定义 ... ``` ### 2)Chart.yaml 文件 ``` apiVersion: chart API 版本 (必需) name: chart名称 (必需) version: chart 版本,语义化2 版本(必需) kubeVersion: 兼容Kubernetes版本的语义化版本(可选) description: 一句话对这个项目的描述(可选) type: chart类型 (可选) keywords: - 关于项目的一组关键字(可选) home: 项目home页面的URL (可选) sources: - 项目源码的URL列表(可选) dependencies: # chart 必要条件列表 (可选) - name: chart名称 (nginx) version: chart版本 ("1.2.3") repository: (可选)仓库URL ("https://example.com/charts") 或别名 ("@repo-name") condition: (可选) 解析为布尔值的yaml路径,用于启用/禁用chart (e.g. subchart1.enabled ) tags: # (可选) - 用于一次启用/禁用 一组chart的tag import-values: # (可选) - ImportValue 保存源值到导入父键的映射。每项可以是字符串或者一对子/父列表项 alias: (可选) chart中使用的别名。当你要多次添加相同的chart时会很有用 maintainers: # (可选) - name: 维护者名字 (每个维护者都需要) email: 维护者邮箱 (每个维护者可选) url: 维护者URL (每个维护者可选) icon: 用做icon的SVG或PNG图片URL (可选) appVersion: 包含的应用版本(可选)。不需要是语义化,建议使用引号 deprecated: 不被推荐的chart (可选,布尔值) annotations: example: 按名称输入的批注列表 (可选). ``` * 从 v3.3.2,不再允许额外的字段。推荐的方法是在 `annotations` 中添加自定义元数据。 * 每个 chart 都必须有个版本号(`version`)。版本必须遵循 语义化版本 2 标准。 不像经典 Helm, Helm v2 以及后续版本会使用版本号作为发布标记。仓库中的包通过名称加版本号标识。 比如 nginx chart 的版本字段 version: 1.2.3 按照名称被设置为: ``` nginx-1.2.3.tgz ``` 【温馨提示】`appVersion`字段与`version`字段并不相关。这是指定应用版本的一种方式。比如,这个 drupal chart 可能有一个 appVersion: "8.2.1",表示包含在 chart(默认)的 Drupal 的版本是 8.2.1。 ### 3)Chart 依赖管理(dependencies) 当前 chart 依赖的其他 chart 会在 dependencies 字段定义为一个列表。 ``` dependencies: - name: apache version: 1.2.3 repository: https://example.com/charts - name: mysql version: 3.2.1 repository: https://another.example.com/charts ``` * name 字段是你需要的 chart 的名称 * version 字段是你需要的 chart 的版本 * repository 字段是 chart 仓库的完整 URL。注意你必须使用 helm repo add 在本地添加仓库 * 你可以使用仓库的名称代替 URL 示例演示: ``` helm repo add bitnami https://charts.bitnami.com/bitnami helm pull bitnami/wordpress tar -xf wordpress cat wordpress/Chart.yaml ``` ![](https://img-blog.csdnimg.cn/7842c4638ea046be86b335d6c462468e.png) 一旦你定义好了依赖,运行 `helm dependency update` 就会使用你的依赖文件下载所有你指定的 chart 到你的 charts / 目录。 ``` helm dependency update ./wordpress ``` 当 helm dependency update 拉取 chart 时,会在 charts / 目录中形成一个 chart 包。因此对于上面的示例,会在 chart 目录中期望看到以下文件: ``` wordpress/charts/ ├── common ├── common-2.0.1.tgz ├── mariadb ├── mariadb-11.2.2.tgz ├── memcached └── memcached-6.2.3.tgz ``` ![](https://img-blog.csdnimg.cn/0688c7848d664d909a5d51035a001dcf.png) **依赖中的 tag 和条件字段** 除了上面的其他字段外,每个需求项可以包含可选字段 `tags` 和 `condition`。**所有的 chart 会默认加载**。如果存在 tags 或者 condition 字段,它们将被评估并用于控制它们应用的 chart 的加载。 * `Condition` ——**条件字段** field 包含一个或多个 YAML 路径(用逗号分隔)。 如果这个路径在上层 values 中已存在并解析为布尔值,chart 会基于布尔值启用或禁用 chart。 只会使用列表中找到的第一个有效路径,如果路径为未找到则条件无效。 * `Tags` ——`tag`字段是与 chart 关联的 YAML 格式的标签列表。在顶层 value 中,通过指定 tag 和布尔值,可以启用或禁用所有的带 tag 的 chart。 ``` # parentchart/Chart.yaml dependencies: - name: subchart1 repository: http://localhost:10191 version: 0.1.0 condition: subchart1.enabled, global.subchart1.enabled tags: - front-end - subchart1 - name: subchart2 repository: http://localhost:10191 version: 0.1.0 condition: subchart2.enabled,global.subchart2.enabled tags: - back-end - subchart2 ``` ``` # parentchart/values.yaml subchart1: enabled: true tags: front-end: false back-end: true ``` * 在上面的例子中,所有带 front-end tag 的 chart 都会被禁用,但只要上层的 value 中 `subchart1.enabled` 路径被设置为 `'true'`,**该条件会覆盖 front-end 标签且 subchart1 会被启用**。 * 一旦 subchart2 使用了 back-end 标签并被设置为了 true,subchart2 就会被启用。 也要注意尽管 subchart2 指定了一个条件字段, 但是上层 value 没有相应的路径和 value,因此这个条件不会生效。 `--set` 参数可以用来设置标签和条件值。 ``` helm install --set tags.front-end=true --set subchart2.enabled=false ``` 标签和条件的解析: * 条件 (当设置在 value 中时)总是会覆盖标签 第一个 chart 条件路径存在时会忽略后面的路径。 * 标签被定义为 '如果任意的 chart 标签是 true,chart 就可以启用'。 * 标签和条件值必须被设置在顶层 value 中。 * value 中的 tags: 键必须是顶层键。 ### 4)通过依赖导入子 Value * 在某些情况下,**允许子 chart 的值作为公共默认传递到父 chart 中**是值得的。使用 `exports`格式的额外好处是它可是将来的工具可以自检用户可设置的值。 * 被导入的包含值的 key 可以在父 chart 的 dependencies 中的 `import-values`字段以 YAML 列表形式指定。 列表中的每一项是从子 chart 中 exports 字段导入的 key。 * 导入 exports key 中未包含的值,使用 **子 - 父格式**。两种格式的示例如下所述。 使用导出格式: 如果子 chart 的 values.yaml 文件中在根节点包含了 exports 字段,它的内容可以通过指定的可以被直接导入到父 chart 的 value 中, 如下所示: ``` # parent's Chart.yaml file dependencies: - name: subchart repository: http://localhost:10191 version: 0.1.0 import-values: - data ``` ``` # child's values.yaml file exports: data: myint: 99 ``` 只要我们再导入列表中指定了键 data,Helm 就会在子 chart 的 exports 字段查找 data 键并导入它的内容。 最终的父级 value 会包含我们的导出字段: ``` # parent's values myint: 99 ``` 【注意】父级键 data 没有包含在父级最终的 value 中,如果想指定这个父级键,要使用`'子-父' 格式`。 下面示例中的`import-values` 指示 Helm 去拿到能再 child: 路径中找到的任何值,并拷贝到 parent: 的指定路径。 ``` # parent's Chart.yaml file dependencies: - name: subchart1 repository: http://localhost:10191 version: 0.1.0 ... import-values: - child: default.data parent: myimports ``` 上面的例子中,在 subchart1 里面找到的 default.data 的值会被导入到父 chart 的 myimports 键中,细节如下: ``` # parent's values.yaml file myimports: myint: 0 mybool: false mystring: "helm rocks!" ``` ``` # subchart1's values.yaml file default: data: myint: 999 mybool: true ``` 父 chart 的结果值将会是这样: ``` # parent's final values myimports: myint: 999 mybool: true mystring: "helm rocks!" ``` 六、Templates and Values ---------------------- ### 1)Templates and Values 简介 * Helm Chart 模板是按照 Go 模板语言书写, 增加了 50 个左右的附加模板函数 来自 Sprig 库 和一些其他 指定的函数。 * 所有模板文件存储在 chart 的 `templates/` 文件夹。 当 Helm 渲染 chart 时,它会通过模板引擎遍历目录中的每个文件。 模板的 Value 通过两种方式提供: * Chart 开发者可以在 chart 中提供一个命名为 `values.yaml` 的文件。这个文件包含了默认值。 * Chart 用户可以提供一个包含了 value 的 YAML 文件。可以在命令行使用 helm install 命令时通过`-f`指定 value 文件。 模板示例 ``` apiVersion: v1 kind: ReplicationController metadata: name: deis-database namespace: deis labels: app.kubernetes.io/managed-by: deis spec: replicas: 1 selector: app.kubernetes.io/name: deis-database template: metadata: labels: app.kubernetes.io/name: deis-database spec: serviceAccount: deis-database containers: - name: deis-database image: {{ .Values.imageRegistry }}/postgres:{{ .Values.dockerTag }} imagePullPolicy: {{ .Values.pullPolicy }} ports: - containerPort: 5432 env: - name: DATABASE_STORAGE value: {{ default "minio" .Values.storage }} ``` 上面的例子,松散地基于 [https://github.com/deis/charts](https://github.com/deis/charts), 是一个 Kubernetes 副本控制器的模板。可以使用下面四种模板值(一般被定义在 values.yaml 文件): * imageRegistry: Docker 镜像的源注册表 * dockerTag: Docker 镜像的 tag * pullPolicy: Kubernetes 的拉取策略 * storage: 后台存储,默认设置为 "minio" ### 2)预定义的 Values Values 通过模板中. Values 对象可访问的 values.yaml 文件(或者通过 --set 参数) 提供, 但可以模板中访问其他预定义的数据片段。 以下值是预定义的,对每个模板都有效,并且可以被覆盖。和所有值一样,名称 区分大小写。 * `Release.Name`: 版本名称 (非 chart 的) * `Release.Namespace`: 发布的 chart 版本的命名空间 * `Release.Service`: 组织版本的服务 * `Release.IsUpgrade`: 如果当前操作是升级或回滚,设置为 true * `Release.IsInstall`: 如果当前操作是安装,设置为 true * `Chart`: `Chart.yaml`的内容。因此,chart 的版本可以从 Chart.Version 获得, 并且维护者在 Chart.Maintainers 里。 * `Files`: chart 中的包含了非特殊文件的类图对象。这将不允许您访问模板, 但是可以访问现有的其他文件(除非被. helmignore 排除在外)。 使用 {{index .Files "file.name"}} 可以访问文件或者使用 {{.Files.Get name }} 功能。 您也可以使用 {{ .Files.GetBytes }} 作为[]byte 访问文件内容。 * `Capabilities`: 包含了 Kubernetes 版本信息的类图对象。({{.Capabilities.KubeVersion}}) 和支持的 Kubernetes API 版本 ({{ .Capabilities.APIVersions.Has "batch/v1" }}) 考虑到前面部分的模板,`values.yaml`文件提供的必要值如下: ``` imageRegistry: "quay.io/deis" dockerTag: "latest" pullPolicy: "Always" storage: "s3" ``` values 文件被定义为 YAML 格式。chart 会包含一个默认的 values.yaml 文件。 Helm 安装命令允许用户使用附加的 YAML values 覆盖这个 values: ``` helm install --generate-name --values=myvals.yaml wordpress ``` ### 3)范围,依赖和值 **Values 文件**可以声明顶级 chart 的值,以及`charts/`目录中包含的其他任意 chart。 或者换个说法,**values 文件可以为 chart 及其任何依赖项提供值**。比如,上面示范的 WordPress chart 同时有 mysql 和 apache 作为依赖。values 文件可以为以下所有这些组件提供依赖: ``` title: "My WordPress Site" # Sent to the WordPress template mysql: max_connections: 100 # Sent to MySQL password: "secret" apache: port: 8080 # Passed to Apache ``` 更**高阶的 chart 可以访问下面定义的所有变量**。因此 **WordPress chart 可以用. Values.mysql.password 访问 MySQL 密码**。 但是**低阶的 chart 不能访问父级 chart**,所以 MySQL 无法访问 title 属性。同样也无法访问 apache.port。 ### 4)全局 Values 从 2.0.0-Alpha.2 开始,Helm 支持特殊的 "global" 值。设想一下前面的示例中的修改版本: ``` title: "My WordPress Site" # Sent to the WordPress template global: app: MyWordPress mysql: max_connections: 100 # Sent to MySQL password: "secret" apache: port: 8080 # Passed to Apache ``` 面添加了 global 部分和一个值 app: MyWordPress。这个值以`.Values.global.app`在 **所有 chart 中有效**。 比如,mysql 模板可以以`{{.Values.global.app}}`访问 app,同样 apache chart 也可以访问。 实际上,上面的 values 文件会重新生成为这样: ``` title: "My WordPress Site" # Sent to the WordPress template global: app: MyWordPress mysql: global: app: MyWordPress max_connections: 100 # Sent to MySQL password: "secret" apache: global: app: MyWordPress port: 8080 # Passed to Apache ``` 七、Helm 资源安装顺序 ------------- * Namespace * NetworkPolicy * ResourceQuota * LimitRange * PodSecurityPolicy * PodDisruptionBudget * ServiceAccount * Secret * SecretList * ConfigMap * StorageClass * PersistentVolume * PersistentVolumeClaim * CustomResourceDefinition * ClusterRole * ClusterRoleList * ClusterRoleBinding * ClusterRoleBindingList * Role * RoleList * RoleBinding * RoleBindingList * Service * DaemonSet * Pod * ReplicationController * ReplicaSet * Deployment * HorizontalPodAutoscaler * StatefulSet * Job * CronJob * Ingress * APIService 八、Helm 安装 Chart 包的三种方式 ---------------------- Helm 自带一个强大的搜索命令,可以用来从两种来源中进行搜索: * `helm search hub` 从 [Artifact Hub](https://artifacthub.io/) 中查找并列出 helm charts。 Artifact Hub 中存放了大量不同的仓库。 * `helm search repo` 从你添加(使用 `helm repo add`)到本地 helm 客户端中的仓库中进行查找。该命令基于本地数据进行搜索,无需连接互联网。 ``` # 添加bitnami仓库源 helm repo add bitnami https://charts.bitnami.com/bitnami # 从bitnami源查找所有chart包,不指定具体源的话,会查找本地添加的所有源地址的所有chart包 helm search repo bitnami ``` ### 1)values 传参 安装过程中有两种方式传递配置数据: * `--values (或 -f)`:使用 YAML 文件覆盖配置。可以指定多次,优先使用最右边的文件。 * `--set`:通过命令行的方式对指定项进行覆盖。 如果同时使用两种方式,则 --set 中的值会被合并到 --values 中,但是 `--set` 中的值**优先级更高**。在 --set 中覆盖的内容会被被保存在 ConfigMap 中。可以通过 `helm get values <release-name>` 来**查看指定 release 中 --set 设置的值**。也可以通过运行 helm upgrade 并指定 --reset-values 字段来清除 --set 中设置的值。示例如下: ``` echo '{mariadb.auth.database: user0db, mariadb.auth.username: user0}' > values.yaml helm install -f values.yaml bitnami/wordpress --generate-name ``` ### 2)【第一种方式】直接在线 安装不需要先下载包到本地 ``` helm install mysql bitnami/mysql helm list ``` ### 3)【第二种方式】离线安装 直接通过安装包安装 ``` # 先删除 helm uninstall mysql # 拉包到本地 helm pull bitnami/mysql # 不解压直接安装 helm install mysql ./mysql-9.3.1.tgz helm list ``` ### 4)【第三种方式】离线安装 解压包再安装 ``` # 拉包到本地 helm pull bitnami/mysql # 解压安装 tar -xf mysql-9.3.1.tgz # 开始安装 helm install mysql ./mysql \ --namespace=mysql \ --create-namespace \ --set image.registry=myharbor.com \ --set image.repository=bigdata/mysql \ --set image.tag=8.0.30 \ --set primary.service.type=NodePort \ --set service.nodePorts.mysql=30306 # 查看在运行的Release helm list # 卸载 helm uninstall mysql -n mysql ``` 九、Helm 基础语法 ----------- ### 1)变量 模板(`templates/`)中的**变量**都放在`{{}}`中,比如:`{{ .Values.images }}` 表示 `Values 对象`下的 images 字段。Values 来源于`values.yaml`文件或者`-f`指定的 yaml 文件,或者`--set`设置的变量。 【温馨提示】使用`-`删除空格和换行符,要想删除那行其他的空格和换行符可以用`{{-`或者`-}}`,**一个是删除左边的`空格`和`换行符`**,**一个是删除右边的`空格`和`换行符`**。 ### 2)内置对象 * `Release`: Release 对象描述了版本发布本身。包含了以下对象: * `Release.Name`: release 名称; * `Release.Namespace`: 版本中包含的命名空间 (如果 manifest 没有覆盖的话); * `Release.IsUpgrade`: 如果当前操作是升级或回滚的话,该值将被设置为 true * `Release.IsInstall`: 如果当前操作是安装的话,该值将被设置为 true * `Release.Revision`: 此次修订的版本号。安装时是 1,每次升级或回滚都会自增; * `Release.Service`: 该 service 用来渲染当前模板。Helm 里始终 Helm。 * `Values`: Values 对象是从`values.yaml`文件和用户提供的文件传进模板的。默认为空 * `Chart`: `Chart.yaml`文件内容。 Chart.yaml 里的所有数据在这里都可以可访问的。比如 {{.Chart.Name}}-{{ .Chart.Version }} 会打印出 mychart-0.1.0。 * `Template`: 包含当前被执行的当前模板信息 * `Template.Name`: 当前模板的命名空间文件路径 (e.g. mychart/templates/mytemplate.yaml); * `Template.BasePath`: 当前 chart 模板目录的路径 (e.g. mychart/templates)。 ### 3)常用的内置函数 #### 1、quote and squote 该函数将值转**换成字符串**用**双引号 (`quote`)** 或者**单引号 (`squote`)** 括起来。示例如下: ``` apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap data: myvalue: "Hello World" drink: {{ .Values.favorite.drink | quote }} food: {{ .Values.favorite.food | upper | quote }} ``` 倒置命令是模板中的常见做法。可以经常看到 `.val | quote` 而不是 `quote .val`。实际上两种操作都是可以的。 #### 2、default 这个函数允许你在模板中指定一个默认值,以防这个值被忽略。 ``` # 如果.Values.favorite.drink是非空值,则使用它,否则会返回tea。 drink: {{ .Values.favorite.drink | default "tea" | quote }} # 还可以这样写,如果.Bar是非空值,则使用它,否则会返回foo。 default "foo" .Bar ``` "空" 定义取决于以下类型: ``` 整型: 0 字符串: "" 列表: [] 字典: {} 布尔: false 以及所有的nil (或 null) ``` #### 3、print 返回各部分组合的字符串,非字符串类型会被转换成字符串。 ``` print "Matt has " .Dogs " dogs" ``` 【温馨提示】当相邻两个参数不是字符串时会在它们之间添加一个空格。 #### 4、println 和 print 效果一样,但会在末尾新添加一行。 #### 5、printf 返回参数按顺序传递的格式化字符串。 ``` printf "%s has %d dogs." .Name .NumberDogs {{- printf "%d" (.Values.externalCache.port | int ) -}} {{- printf "%s" .Values.existingSecret -}} {{- printf "%v" .context.Values.redis.enabled -}} # %s 字符串占位符,未解析的二进制字符串或切片 # %d 数字占位符,十进制 # %v 默认格式的值,当打印字典时,加号参数(%+v)可以添加字段名称 ``` 更多占位符的使用,可以参考官方文档:[https://helm.sh/zh/docs/chart_template_guide/function_list/](https://helm.sh/zh/docs/chart_template_guide/function_list/) #### 6、trim trim 行数移除字符串两边的空格: ``` trim " hello " ``` #### 7、trimAll 从字符串中移除给定的字符: ``` trimAll "$" "$5.00" ``` 上述结果为:5.00 (作为一个字符串)。 #### 8、lower 将整个字符串转换成小写: ``` lower "HELLO" ``` 上述结果为: hello #### 9、upper 将整个字符串转换成大写: ``` upper "hello" ``` 上述结果为: HELLO #### 10、title 首字母转换成大写: ``` title "hello world" ``` 上述结果为: Hello World #### 11、substr 获取字符串的子串,有三个参数: * start (int) * end (int) * string (string) ``` substr 0 5 "hello world" ``` 上述结果为: hello #### 12、abbrev 用省略号截断字符串 (...) ``` abbrev 5 "hello world" # 第一个参数:最大长度 # 第二个参数:字符串 ``` 上述结果为: he..., 因为将省略号算进了长度中。 #### 13、contains 测试字符串是否包含在另一个字符串中: ``` contains "cat" "catch" ``` #### 14、cat cat 函数将多个字符串合并成一个,用空格分隔: ``` cat "hello" "beautiful" "world" ``` 上述结果为: hello beautiful world #### 15、indent indent 以**指定长度缩进**给定字符串所在行,在对齐多行字符串时很有用: ``` indent 4 $lots_of_text ``` 上述结果会将每行缩进 4 个空格。 #### 16、nindent nindent 函数和 indent 函数一样,但可以在字符串开头添加新行。 ``` nindent 4 $lots_of_text ``` 上述结果会在字符串所在行缩进 4 个字符,并且在开头新添加一行。 #### 17、replace 执行简单的字符串替换。 ``` # 下面两行等价 replace " " "-" "I Am Henry VIII" "I Am Henry VIII" | replace " " "-" # 参数1:待替换字符串 # 参数2:要替换字符串 # 参数3:源字符串 ``` 上述结果为: I-Am-Henry-VIII #### 18、date date 函数格式化日期,日期格式化为 YEAR-MONTH-DAY: ``` now | date "2006-01-02" ``` 想了解更多内置函数,可以参考官方文档:[https://helm.sh/zh/docs/chart_template_guide/function_list/](https://helm.sh/zh/docs/chart_template_guide/function_list/) ### 4)类型转换函数 Helm 提供了以下类型转换函数: * `atoi`: 字符串转换成整型。 * `float64`: 转换成 float64。 * `int`: 按系统整型宽度转换成 int。 * `int64`: 转换成 int64。 * `toDecimal`: 将 unix 八进制转换成 int64。 * `toString`: 转换成字符串。 * `toStrings`: 将列表、切片或数组转换成字符串列表。 * `toJson (mustToJson)`: 将列表、切片、数组、字典或对象转换成 JSON。 * `toPrettyJson (mustToPrettyJson)`: 将列表、切片、数组、字典或对象转换成格式化 JSON。 * `toRawJson (mustToRawJson)`: 将列表、切片、数组、字典或对象转换成 HTML 字符未转义的 JSON。 ### 5)正则表达式(Regular Expressions) Helm 包含以下正则表达式函数 * regexFind(mustRegexFind) * regexFindAll(mustRegexFindAll) * regexMatch (mustRegexMatch) * regexReplaceAll (mustRegexReplaceAll) * regexReplaceAllLiteral(mustRegexReplaceAllLiteral) * regexSplit (mustRegexSplit) ### 6)编码和解码函数 Helm 有以下编码和解码函数: * b64enc/b64dec: 编码或解码 Base64 * b32enc/b32dec: 编码或解码 Base32 ### 7)Dictionaries and Dict Functions Helm 提供了一个 key/value 存储类型称为 dict("dictionary" 的简称,Python 中也有)。dict 是无序类型。**字典的 key 必须是字符串**。**但值可以是任意类型,甚至是另一个 dict 或 list**。 #### 1、创建字典(dict) 下面是创建三个键值对的字典: ``` $myDict := dict "name1" "value1" "name2" "value2" "name3" "value 3" ``` #### 2、获取值(get) 给定一个映射和一个键,从映射中获取值。 ``` get $myDict "name1" ``` 上述结果为: "value1" 注意如果没有找到,会简单返回 ""。不会生成 error。 #### 3、添加键值对(set) 使用 set 给字典添加一个键值对。 ``` $_ := set $myDict "name4" "value4" ``` 注意 set 返回字典 (Go 模板函数的一个要求),因此你可能需要像上面那样使用使用`$_`赋值来获取值。 #### 4、删除(unset) 给定一个映射和 key,从映射中删除这个 key。 ``` $_ := unset $myDict "name4" ``` 和 set 一样,需要返回字典。 #### 5、判断 key(hasKey) hasKey 函数会在给定字典中包含了给定 key 时返回 true。 ``` hasKey $myDict "name1" ``` 如果 key 没找到,会返回 false。 #### 6、pluck pluck 函数给定一个键和多个映射,并获得所有匹配项的列表: ``` pluck "name1" $myDict $myOtherDict ``` 上述会返回的 list 包含了每个找到的值 ([value1 otherValue1])。 #### 7、合并 dict(merge, mustMerge) 将两个或多个字典合并为一个, 目标字典优先: ``` $newdict := merge $dest $source1 $source2 ``` #### 8、获取所有 keys keys 函数会返回一个或多个 dict 类型中所有的 key 的 list。由于字典是 无序的,key 不会有可预料的顺序。 可以使用 sortAlpha 存储。 ``` keys $myDict | sortAlpha ``` 当提供了多个词典时,key 会被串联起来。使用`uniq`函数和`sortAlpha`获取一个唯一有序的键列表。 ``` keys $myDict $myOtherDict | uniq | sortAlpha ``` #### 9、获取所有 values values 函数类似于 keys,返回一个新的 list 包含源字典中所有的 value(只支持一个字典)。 ``` $vals := values $myDict ``` 上述结果为: list["value1", "value2", "value 3"]。 注意 values 不能保证结果的顺序;如果你需要顺序, 请使用`sortAlpha`。 ### 8)Lists and List Functions Helm 提供了一个简单的 list 类型,包含任意顺序的列表。类似于数组或切片,但列表是被设计用于不可变数据类型。 #### 1、创建列表 ``` $myList := list 1 2 3 4 5 ``` 上述会生成一个列表 [1 2 3 4 5]。 #### 2、获取列表第一项(first, mustFirst) 获取列表中的第一项,使用 first。 ``` first $myList # 返回 1 ``` first 有问题时会出错,mustFirst 有问题时会向模板引擎返回错误。 #### 3、获取列表的尾部内容(rest, mustRest) 获取列表的尾部内容 (除了第一项外的所有内容),使用 rest。 ``` rest $myList # 返回 [2 3 4 5] ``` rest 有问题时会出错,mustRest 有问题时会向模板引擎返回错误。 #### 4、获取列表的最后一项(last, mustLast) 使用 last 获取列表的最后一项: ``` last $myList # 返回 5。这大致类似于反转列表然后调用first。 ``` #### 5、获取列表所有内容(initial, mustInitial) 通过返回所有元素 但 除了最后一个元素。 ``` initial $myList # 返回 [1 2 3 4]。 ``` initial 有问题时会出错,但是 mustInitial 有问题时会向模板引擎返回错误。 #### 6、末尾添加元素(append, mustAppend) 在已有列表中追加一项,创建一个新的列表。 ``` $new = append $myList 6 ``` 上述语句会设置 $new 为 [1 2 3 4 5 6]。 $myList 会保持不变。 append 有问题时会出错,但 mustAppend 有问题时会向模板引擎返回错误。 #### 7、前面添加元素(prepend, mustPrepend) 将元素添加到列表的前面,生成一个新的列表。 ``` prepend $myList 0 ``` 上述语句会生成 [0 1 2 3 4 5]。 $myList 会保持不变。 prepend 有问题时会出错,但 mustPrepend 有问题时会向模板引擎返回错误。 #### 8、多列表连接(concat) 将任意数量的列表串联成一个。 ``` concat $myList ( list 6 7 ) ( list 8 ) ``` 上述语句会生成 [1 2 3 4 5 6 7 8]。 $myList 会保持不变。 #### 9、反转(reverse, mustReverse) 反转给定的列表生成一个新列表。 ``` reverse $myList ``` 上述语句会生成一个列表: [5 4 3 2 1]。 reverse 有问题时会出错,但 mustReverse 有问题时会向模板引擎返回错误。 #### 10、去重(uniq, mustUniq) 生成一个移除重复项的列表。 ``` list 1 1 1 2 | uniq ``` 上述语句会生成 [1 2] uniq 有问题时会出错,但 mustUniq 有问题时会向模板引擎返回错误。 #### 11、过滤(without, mustWithout) without 函数从列表中过滤内容。 ``` without $myList 3 # 上述语句会生成 [1 2 4 5] ``` 一个过滤器可以过滤多个元素: ``` without $myList 1 3 5 # 这样会得到: [2 4] ``` without 有问题时会出错,但 mustWithout 有问题时会向模板引擎返回错误。 #### 12、判断元素是否存在(has, mustHas) 验证列表是否有特定元素。 ``` has 4 $myList ``` 上述语句会返回 true, 但 has "hello" $myList 就会返回 false。 has 有问题时会出错,但 mustHas 有问题时会向模板引擎返回错误。 #### 13、删除空项(compact, mustCompact) 接收一个列表并删除空值项。 ``` $list := list 1 "a" "foo" "" $copy := compact $list ``` compact 会返回一个移除了空值 (比如, "") 的新列表。 compact 有问题时会出错,但 mustCompact 有问题时会向模板引擎返回错误。 #### 14、index 使用 index list [n] 获取列表的第 n 个元素。使用 index list [n] [m] ... 获取多位列表元素。 * index $myList 0 返回 1,同 myList[0] * index $myList 0 1 同 myList[0][1] #### 15、获取部分元素(slice, mustSlice) 从列表中获取部分元素,使用 slice list [n] [m]。等同于 list[n:m]. * slice $myList 返回 [1 2 3 4 5]。 等同于 myList[:]。 * slice $myList 3 返回 [4 5] 等同于 myList[3:]。 * slice $myList 1 3 返回 [2 3] 等同于 myList[1:3]。 * slice $myList 0 3 返回 [1 2 3] 等同于 myList[:3]。 slice 有问题时会出错,但 mustSlice 有问题时会向模板引擎返回错误。 #### 16、构建一个整数列表(until) until 函数构建一个整数范围。 ``` until 5 ``` 上述语句会生成一个列表: [0, 1, 2, 3, 4]。 对循环语句很有用: range $i, $e := until 5。 #### 17、seq ``` seq 5 => 1 2 3 4 5 seq -3 => 1 0 -1 -2 -3 seq 0 2 => 0 1 2 seq 2 -2 => 2 1 0 -1 -2 seq 0 2 10 => 0 2 4 6 8 10 seq 0 -2 -5 => 0 -2 -4 ``` ### 9)数学函数(Math Functions) #### 1、求和(add) 使用 add 求和。接受两个或多个输入。 ``` add 1 2 3 ``` #### 2、自加 1(add1) 自增加 1,使用 add1。 #### 3、相减(sub) 相减使用 sub。 #### 4、除(div) 整除使用 div。 #### 5、取模(mod) 取模使用 mod。 #### 6、相乘(mul) 相乘使用 mul。接受两个或多个输入。 ``` mul 1 2 3 ``` #### 7、获取最大值(max) 返回一组整数中最大的整数。 ``` max 1 2 3 # 返回 3 ``` #### 8、获取最小值(min) 返回一组数中最小的数。 ``` min 1 2 3 # 会返回 1。 ``` #### 9、获取长度(len) 以整数返回参数的长度。 ``` len .Arg ``` #### 10)Network Functions Helm 提供了几个网络函数: * `getHostByName`接收一个域名返回 IP 地址。 * `getHostByName` "www.google.com" 会返回对应的 www.google.com 的地址。 ### 10)条件语句 **运算符:** ``` eq: 等于(equal to) ne: 不等于(not equal to) lt: 小于(less than) le: 小于等于(less than or equal to) gt: 大于(greater than) ge: 大于等于(greater than or equal to) ``` **if/else 用法:** ``` {{if 命令}} … {{else if 命令}} … {{else}} … {{end}} ``` 如果是以下值时,管道会被设置为 false: ``` 布尔false 数字0 空字符串 nil (空或null) 空集合(map, slice, tuple, dict, array) ``` 【示例】 ``` apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap data: myvalue: "Hello World" drink: {{ .Values.favorite.drink | default "tea" | quote }} food: {{ .Values.favorite.food | upper | quote }} {{ if eq .Values.favorite.drink "coffee" }}mug: "true"{{ end }} ``` ### 11)变更作用域 with 下一个控制结构是`with`操作。这个用来**控制变量范围**。回想一下,`.`是对 当前作用域 的引用。因此 `.Values`就是告诉模板在当前作用域查找 Values 对象。 with 的语法与 if 语句类似: ``` {{ with PIPELINE }} # restricted scope {{ end }} ``` 作用域可以被改变。with 允许你为特定对象设定当前作用域 (`.`)。比如,我们已经在使用. Values.favorite。 修改配置映射中的. 的作用域指向. Values.favorite: ``` apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap data: myvalue: "Hello World" {{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} {{- end }} ``` 但是这里有个注意事项,在限定的作用域内,**无法使用. 访问父作用域**的对象。错误示例如下: ``` {{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} release: {{ .Release.Name }} {{- end }} ``` 这样会报错因为`Release.Name`**不在`.`限定的作用域内**。但是如果对调最后两行就是正常的, 因为在 {{end}} 之后作用域被重置了。 ``` {{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} {{- end }} release: {{ .Release.Name }} ``` 或者,我们可以使用`$`**从父作用域中访问 Release.Name 对象**。当模板开始执行后`$`会被映射到**根作用域**,且执行过程中不会更改。 下面这种方式也可以正常工作: ``` {{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} release: {{ $.Release.Name }} {{- end }} ``` 也可以在外边定义变量,遵循`$name变量`的格式且指定了一个特殊的赋值运算符:`:=`。 我们可以使用针对 Release.Name 的变量重写上述内容。 ``` apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap data: myvalue: "Hello World" {{- $relname := .Release.Name -}} {{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} release: {{ $relname }} {{- end }} ``` 注意在 with 块开始之前,赋值`$relname := .Release.Name`。 现在在 with 块中,$relname 变量仍会执行版本名称。 ### 12)rang 循环语句 很多编程语言支持使用 for 循环,foreach 循环,或者类似的方法机制。 在 Helm 的模板语言中,在一个集合中迭代的方式是使用`range`操作符。 定义 values ``` favorite: drink: coffee food: pizza pizzaToppings: - mushrooms - cheese - peppers - onions ``` 现在我们有了一个 pizzaToppings 列表(模板中称为切片)。修改模板把这个列表打印到配置映射中: ``` apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap data: myvalue: "Hello World" {{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} {{- end }} toppings: |- {{- range .Values.pizzaToppings }} - {{ . | title | quote }} {{- end }} ``` 有时能在模板中快速创建列表然后迭代很有用,Helm 模板的 tuple 可以很容易实现该功能。在计算机科学中, 元组表示一个有固定大小的类似列表的集合,但可以是任意数据类型。这大致表达了`tuple`的用法。 ``` sizes: |- {{- range tuple "small" "medium" "large" }} - {{ . }} {{- end }} ``` 上述模板会生成以下内容: ``` sizes: |- - small - medium - large ``` ### 13)命名模板 此时需要越过模板,开始创建其他内容了。该部分我们会看到如何在一个文件中定义 命名模板,并在其他地方使用。**命名模板** (有时称作一个 部分 或一个 子模板) 仅仅是在文件内部定义的模板,并使用了一个名字。有两种创建方式和几种不同的使用方法。 * 三种声明和管理模板的方法:`define`,`template`,和`block`,在这部分,我们将使用这三种操作并介绍一种特殊用途的 `include`方法,类似于 template 操作。 * 命名模板时要记住一个重要细节:**模板名称是全局的**。如果您想声明两个相同名称的模板,**哪个最后加载就使用哪个**。 因为在子 chart 中的模板和顶层模板一起编译,命名时要注意 chart 特定名称。 * 一个常见的命名惯例是用 chart 名称作为模板前缀:`{{ define "mychart.labels" }}`。使用**特定 chart 名称作为前缀**可以**避免可能因为 两个不同 chart 使用了相同名称的模板**而引起的冲突。 在编写模板细节之前,文件的命名惯例需要注意: * templates / 中的大多数文件被视为包含 Kubernetes 清单 * NOTES.txt 是个例外 * 命名以下划线 (`_`) 开始的文件则假定 没有 包含清单内容。这些文件不会渲染为 Kubernetes 对象定义,但在其他 chart 模板中都可用。 这些文件用来存储局部和辅助对象,实际上当我们第一次创建 mychart 时,会看到一个名为`_helpers.tpl`的文件,这个文件是**模板局部的默认位置**。 #### 1、用 define 和 template 声明和使用模板 define 操作允许我们在模板文件中创建一个命名模板,**语法**如下: ``` {{- define "MY.NAME" }} # body of template here {{- end }} ``` 比如我们可以定义一个模板封装 Kubernetes 的标签: ``` {{- define "mychart.labels" }} labels: generator: helm date: {{ now | htmlDate }} {{- end }} ``` 现在我们将模板嵌入到了已有的配置映射中,然后使用`template`包含进来: ``` {{- define "mychart.labels" }} labels: generator: helm date: {{ now | htmlDate }} {{- end }} apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap {{- template "mychart.labels" }} data: myvalue: "Hello World" {{- range $key, $val := .Values.favorite }} {{ $key }}: {{ $val | quote }} {{- end }} ``` 当模板引擎读取该文件时,它会存储 mychart.labels 的引用直到 template "mychart.labels" 被调用。 然后会按行渲染模板,因此结果类似这样: ``` # Source: mychart/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: running-panda-configmap labels: generator: helm date: 2022-09-04 data: myvalue: "Hello World" drink: "coffee" food: "pizza" ``` 注意:define 不会有输出,除非像本示例一样用模板调用它。 按照惯例,Helm chart 将这些模板放置在局部文件中,一般是`_helpers.tpl`。把这个方法移到那里: ``` {{/* Generate basic labels */}} {{- define "mychart.labels" }} labels: generator: helm date: {{ now | htmlDate }} {{- end }} ``` #### 2、设置模板范围 在上面定义的模板中,我们没有使用任何对象,仅仅使用了方法。修改定义好的模板让其包含 chart 名称和版本号: ``` {{/* Generate basic labels */}} {{- define "mychart.labels" }} labels: generator: helm date: {{ now | htmlDate }} chart: {{ .Chart.Name }} version: {{ .Chart.Version }} {{- end }} ``` #### 3、include 方法 假设定义了一个简单模板如下: ``` {{- define "mychart.app" -}} app_name: {{ .Chart.Name }} app_version: "{{ .Chart.Version }}" {{- end -}} ``` 现在假设我想把这个插入到模板的 labels: 部分和 data: 部分: ``` apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap labels: {{ template "mychart.app" . }} data: myvalue: "Hello World" {{- range $key, $val := .Values.favorite }} {{ $key }}: {{ $val | quote }} {{- end }} {{ template "mychart.app" . }} ``` 如果渲染这个,会得到以下错误: ``` $ helm install --dry-run measly-whippet ./mychart Error: unable to build kubernetes objects from release manifest: error validating "": error validating data: [ValidationError(ConfigMap): unknown field "app_name" in io.k8s.api.core.v1.ConfigMap, ValidationError(ConfigMap): unknown field "app_version" in io.k8s.api.core.v1.ConfigMap] ``` 要查看渲染了什么,可以用`--disable-openapi-validation`参数重新执行: `helm install --dry-run --disable-openapi-validation measly-whippet ./mychart`。 输入不是我们想要的: ``` # Source: mychart/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: measly-whippet-configmap labels: app_name: mychart app_version: "0.1.0" data: myvalue: "Hello World" drink: "coffee" food: "pizza" app_name: mychart app_version: "0.1.0" ``` 注意两处的 **app_version 缩进都不对**,为啥?因为被替换的模板中文本是左对齐的。由于`template`是一个行为,**不是方法**,**无法将 `template`调用的输出传给其他方法,数据只是简单地按行插入**。 为了处理这个问题,Helm 提供了一个`include`,可以将模板内容导入当前管道,然后传递给管道中的其他方法。下面这个示例,使用`indent`正确地缩进了 mychart.app 模板: ``` apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }}-configmap labels: {{ include "mychart.app" . | indent 4 }} data: myvalue: "Hello World" {{- range $key, $val := .Values.favorite }} {{ $key }}: {{ $val | quote }} {{- end }} {{ include "mychart.app" . | indent 2 }} ``` 现在生成的 YAML 每一部分都可以正确缩进了: ``` # Source: mychart/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: edgy-mole-configmap labels: app_name: mychart app_version: "0.1.0" data: myvalue: "Hello World" drink: "coffee" food: "pizza" app_name: mychart app_version: "0.1.0" ``` `include` 相较于使用 template,在 helm 中**使用 include 被认为是更好的方式** 只是为了更好地处理 YAML 文档的输出格式。 ### 14)NOTES.txt 文件 该部分会**介绍为 chart 用户提供说明的 Helm 工具**。在 helm install 或 helm upgrade 命令的最后,**Helm 会打印出对用户有用的信息**。 使用模板可以高度自定义这部分信息。 要在 chart 添加安装说明,只需创建`templates/NOTES.txt`文件即可。**该文件是纯文本,但会像模板一样处理**, 所有正常的模板函数和对象都是可用的。让我们创建一个简单的 NOTES.txt 文件: ``` Thank you for installing {{ .Chart.Name }}. Your release is named {{ .Release.Name }}. To learn more about the release, try: $ helm status {{ .Release.Name }} $ helm get all {{ .Release.Name }} ``` 现在如果我们执行 helm install rude-cardinal ./mychart 会在底部看到: ``` RESOURCES: ==> v1/Secret NAME TYPE DATA AGE rude-cardinal-secret Opaque 1 0s ==> v1/ConfigMap NAME DATA AGE rude-cardinal-configmap 3 0s NOTES: Thank you for installing mychart. Your release is named rude-cardinal. To learn more about the release, try: $ helm status rude-cardinal $ helm get all rude-cardinal ``` 使用 NOTES.txt 这种方式是给用户提供关于如何使用新安装的 chart 细节信息的好方法。尽管并不是必需的,**强烈建议创建一个`NOTES.txt`文件**。 ### 15)模板调试 调试模板可能很棘手,因为渲染后的模板发送给了 Kubernetes API server,可能会以格式化以外的原因拒绝 YAML 文件。以下命令有助于调试: * `helm lint` 是验证 chart 是否遵循最佳实践的首选工具 * `helm install --dry-run --debug` 或 `helm template --debug`:我们已经看过这个技巧了, 这是让服务器渲染模板的好方法,然后返回生成的清单文件。 * `helm get manifest`: 这是查看安装在服务器上的模板的好方法。 当你的 YAML 文件解析失败,但你想知道生成了什么,检索 YAML 一个简单的方式是**注释掉模板中有问题的部分**, 然后重新运行 `helm install --dry-run --debug`: ``` apiVersion: v2 # some: problem section # {{ .Values.foo | quote }} ``` 以上内容会被渲染同时返回完整的注释: ``` apiVersion: v2 # some: problem section # "bar" ``` 其实这里主要是正对官方文档进行整理,列出了常见的使用语法,想了解更多,可以参考[官方文档](https://helm.sh/zh/docs/),官方文档讲解的很细致,有疑问的小伙伴欢迎给我留言哦,后续会持续分享【云原生和大数据】相关的文章,请小伙伴耐心等待哦~
Jonny
Sept. 10, 2022, 2:43 p.m.
181
0 条评论
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
如遇文档失效,可评论告知,便后续更新!
【腾讯云】2核2G云服务器新老同享 99元/年,续费同价
【阿里云】2核2G云服务器新老同享 99元/年,续费同价(不要✓自动续费)
【腾讯云】2核2G云服务器新老同享 99元/年,续费同价
【阿里云】2核2G云服务器新老同享 99元/年,续费同价(不要✓自动续费)
Markdown文件
Word文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
有效期