DevOps - Overview
演进过程精益
诞生于工业领域:用最少的时间和资源消耗,生产出高质量的产品
瀑布模式
线性的开发流程、将软件开发划分为一系列阶段
敏捷模式
误区:敏捷 = 管理
敏捷是基于精益的思想
将开发过程拆分成 N 个敏捷开发周期,小步快跑
生命周期
基于迭代的敏捷(固定的迭代周期)
基于流程的敏捷(不固定的迭代周期)
运维不堪重负,建立部门墙,敏捷模式只关注开发,不关注运维
DevOps
核心阶段
版本控制
持续集成 - 代码提交
持续交付 - 测试环境
持续部署 - 生产环境
持续监控
源码管理
SVN / Git
Git Flow
git pull = git fetch + git merge
Git 高级用法rebase
将一个分支的提交移动到另一个分支的末尾,使得提交历史更加线性和整洁
主要场景:
更新本地分支以匹配远程分支,避免产生多余的 merge commit
合并提交
重新排列提交
12$ git checkout feature$ git rebase master
从两个分支的共同祖先开始提取待变基分支(featu ...
Kubernetes - Security
层次模型
开发
分发
部署
运行时
容器运行时Non-root
在 Dockerfile 中通过 USER 命令切换成非 root 用户
防止某些镜像窃取宿主的 root 权限并造成危害
在某些容器运行时,容器内部的 root 用户与宿主上的 root 用户是同一个用户
宿主上的重要文件被 mount 到容器内,并被容器修改配置
即使在容器内部也应该权限隔离
123FROM ubuntuRUN user add AUSER A
User namespace
依赖 User namespace,任何容器内部的用户都会映射为宿主上的非 root 用户
默认关闭,因为会引入配置复杂性
系统不知道宿主用户与容器用户的映射关系,在 mount 文件时无法设置适当的权限
Rootless container
容器运行时以非 root 身份启动
即使容器被攻破,在宿主层面获得的用户权限也是非 root 用户
Docker 和其它容器运行时本身的后台 Daemon 需要以 root 身份运行,其它的用户容器才能以 rootless 身份运行
某些运行时,如 Podman,没有 Daemon 进程,也就完 ...
Kubernetes - Federation
跨地域
使用单一集群,可以管控多个地域的机器,底层网络需要打通
Service 优先级:zone > region > other
集群联邦必要性
单一集群的管理规模有上限
数据库存储
etcd 作为 Kubernetes 集群的后端存储数据库,对空间大小(8G)的要求比较苛刻
内存占用
Kubernetes 的 API Server 作为 API 网关,会缓存该集群的所有对象
其它的 Kubernetes Controller 也需要对监听的对象构建客户端缓存
控制器复杂度
Kubernetes 的一个业务流程由多个对象和控制器联动完成
随着对象数量的增长,控制器的处理耗时也会增长
单一计算节点的资源有上限
可量化资源:CPU、Memory 等
不可量化资源:端口数量(限制 Service NodePort)、进程数量等
故障域控制
集群规模越大,控制面组件出现故障时的影响范围越大
方案:将大规模的数据中心切成多个规模相对较小的集群,每个集群控制在一定规模
应用 HA
多数据中心部署来保障跨地域高可用
混合云
私有云 + 公有云
职责
跨集群同步资源 ...
Kubernetes - Istio
CRD
核心为 networking
12345678910111213141516171819202122$ istioctl versionclient version: 1.19.3control plane version: 1.19.3data plane version: 1.19.3 (2 proxies)$ k get crdNAME CREATED ATauthorizationpolicies.security.istio.io 2022-12-27T02:58:37Zdestinationrules.networking.istio.io 2022-12-27T02:58:37Zenvoyfilters.networking.istio.io 2022-12-27T02:58:37Zgateways.networking.istio.io 2022-12-27T02:58:37Zistiooperators.install.istio.io ...
Kubernetes - Envoy
Kubernetes
Kubernetes 主要基于 Kernel 技术栈,缺少精细化的高级流量治理
Kubernetes 已有的流量治理能力:Service + Ingress
Service 在 L4,基于 Kernel 技术栈,无法实现精细化的高级流量管理
Ingress 在 L7,主要针对入站流量
架构演进单体
访问服务
微服务
业务代码一般会集成统一的 SDK,耦合了很多平台侧的能力
Service MeshSidecar
Service Instance 与 Sidecar Proxy 在同一个 Network Namespace,相当于一个 loopback,可以明文传输
能力下沉
通过 Sidecar 来实现微服务治理,业务部门更聚焦于业务逻辑
Istio特性
HTTP、gRPC、WebSocket、TCP 的自动负载均衡
通过丰富的路由规则实现重试、故障转移、故障注入,可以对流量行为进行细粒度控制
可插入的策略层和配置 API,支持访问控制、速率限制和配额
对出入集群入口和出口中的所有流量的自动度量指标、日志记录和跟踪
通过强大的基于身份的验证和授权,在集群 ...
Kubernetes - Scaling
Aggregated APIServer
123456789101112131415161718192021222324$ k get apiservices.apiregistration.k8s.ioNAME SERVICE AVAILABLE AGEv1. Local True 36dv1.admissionregistration.k8s.io Local True 36dv1.apiextensions.k8s.io Local True 36dv1.apps Local True ...
Kubernetes - Helm
特性
Helm Chart 是创建一个应用实例的必要的配置组,即 Spec 集合
配置信息被归类为模板和值,经过渲染后生成最终的对象
所有配置可以被打包进一个可以发布的对象中
Release 为一个特定配置的 Chart 的实例
组件
只有客户端,没有服务端
Client
本地 Chart 开发
管理 Repository
管理 Release
与 Library 交互
发送需要安装的 Chart
请求升级或者卸载存在的 Release
Library
负责与 API Server 交互
基于 Chart 和 Configuration 创建一个 Release
把 Chart 安装到 Kubernetes,并提供相应的 Release 对象
升级 + 卸载
采用 Kubernetes 存储所有配置信息 - 无需服务端
实践
开发
123456789101112131415161718$ h create myappCreating myapp$ tree myappmyapp├── Chart.yaml├── charts├── templates│ ├── NOTES.txt│ ...
Kubernetes - Operator
应用接入应用容器化开销风险
Log Driver
Blocking mode
Non-Blocking mode
共享 Kernel
共享系统参数配置
进程数共享
fd 数共享
主机磁盘共享
资源监控应用视角
容器中看到的资源是主机资源
top
Java Runtime.availableProcessors()
cat /proc/cpuinfo
cat /proc/meminfo
df -k
影响应用
Java
Concurrent GC Thread
Heap Size
线程数不可控
判断规则
查询 /proc/1/cgroup 是否包含 kubepods 关键字
12345678910111213141516171819202122232425262728293031323334$ cat /proc/1/cgroup12:cpuset:/11:devices:/init.scope10:blkio:/init.scope9:freezer:/8:net_cls,net_prio:/7:pids:/init.scope6:perf_ ...
Go - Pointer
指针类型
指针类型是依托某一类型而存在的
对于某一类型 T,以 T 为基类型的指针类型为 *T
unsafe.Pointer 不需要基类型,用于表示一个通用指针类型
任何指针类型和 unsafe.Pointer 可以相互显式转换
1234567type T struct{}func main() { var p *T var p1 = unsafe.Pointer(p) // 任意指针类型 -> unsafe.Pointer p = (*T)(p1) // unsafe.Pointer -> 任意指针类型}
如果指针类型变量没有被显式赋予初值,默认值为 nil
123456type T struct{}func main() { var p *T println(p == nil) // true}
给指针类型变量赋值
123var a int = 13var p *int = &a // & 为 ...
Go - Type Constraint
限制
对泛型函数的类型参数以及泛型函数中的实现代码设置限制
泛型函数的调用者只能传递满足限制条件的类型实参
泛型函数内部也只能以类型参数允许的方式使用这些类型实参值
在 Go 中,使用类型参数约束来表达这种限制条件
函数普通参数在函数实现中可以表现出来的性质与可以参与的运算由参数类型限制
泛型函数的类型参数由约束来限制
内置约束any
最宽松的约束
无论是泛型函数还是泛型类型,其所有的类型参数声明中都必须显式包含约束
可以使用空接口类型来表达所有类型
123func foo[T interface{}](sl []T) {}func bar[T1 interface{}, T2 interface{}](t1 T1, t2 T2) {}
空接口类型的不足:使得声明变得冗长、复杂、语义不清
builtin/builtin.go12// any is an alias for interface{} and is equivalent to interface ...