02. 为何使用K8s
为何使用K8s
K8s 的功能特性
功能
-
服务发现和负载平衡:
K8s 可以使用DNS 名称或使用自己的IP 地址暴露容器。如果容器的流量很高,K8s 能够负载均衡并分配网络流量,以便部署稳定。 -
存储编排:
K8s 允许您自动安装您选择的存储系统,例如本地存储,公共云提供商等。 -
自动部署和回滚:您可以使用
K8s 描述已部署容器的所需状态,并且可以以受控速率将实际状态更改为所需状态。例如,您可以自动化K8s 为您的部署创建新容器,删除现有容器并将所有资源用于新容器。 -
自动装箱:
K8s 允许您指定每个容器需要多少CPU 和内存(RAM) 。当容器指定了资源请求时,K8s 可以更好地决定管理容器的资源。 -
自我修复:
K8s 重新启动失败的容器,替换容器,杀死不响应用户定义的运行状况检查的容器,并且在它们准备好服务之前不会将它们通告给客户端。 -
密钥和配置管理:
K8s 允许您存储和管理敏感信息,例如密码,OAuth 令牌和ssh 密钥。您可以部署和更新机密和应用程序配置,而无需重建容器映像,也不会在堆栈配置中暴露机密。
优势
-
它的速度很快:在不停机的情况下持续部署新功能时,
K8s 是一个完美的选择。K8s 的目标是以恒定的正常运行时间更新应用程序。它的速度通过您每小时可以运送的许多功能来衡量,同时保持可用的服务。以正确的方式使用K8s 可帮助DevOps 即服务团队自动扩展应用程序并以零停机时间进行更新。 -
遵循不可变基础架构的原则:以传统方式,如果多个更新出现任何问题,您就没有任何记录显示您部署了多少更新以及发生了哪个错误。在不可变基础结构中,如果您希望更新任何应用程序,则需要使用新标记构建容器映像并进行部署,从而使用旧映像版本终止旧容器。通过这种方式,您将获得一份记录,并了解您所做的事情以及是否有任何错误
; 您可以轻松回滚到上一个图像。 -
提供声明性配置:用户可以知道系统应该处于什么状态以避免错误。作为传统工具的源代码控制,单元测试等不能与命令式配置一起使用,但可以与声明性配置一起使用。
-
大规模部署和更新软件:由于
K8s 具有不可变的声明性,因此扩展很容易。K8s 提供了一些用于扩展目的的有用功能:- 水平基础架构缩放:在单个服务器级别执行操作以应用水平缩放。可以毫不费力地添加或分离
atest 服务器。 - 自动扩展:根据
CPU 资源或其他应用程序指标的使用情况,您可以更改正在运行的容器数 - 手动缩放:您可以通过命令或界面手动缩放正在运行的容器的数量
- 复制控制器:复制控制器确保群集在运行条件下具有指定数量的等效窗格。如果存在太多
Pod ,则复制控制器可以删除额外的Pod ,反之亦然。
- 水平基础架构缩放:在单个服务器级别执行操作以应用水平缩放。可以毫不费力地添加或分离
-
处理应用程序的可用性:
K8s 检查节点和容器的运行状况,并在由于错误导致的盒中崩溃时提供自我修复和自动替换。此外,它在多个Pod 之间分配负载,以便在意外流量期间快速平衡资源。 -
存储卷:在
K8s 中,数据在容器之间共享,但如果Pod 被杀死,则会自动删除卷。此外,数据是远程存储的,因此如果将Pod 移动到另一个节点,数据将保留,直到用户删除为止。
不足
-
初始过程需要时间:创建新进程时,您必须等待应用程序开始,然后才能供用户使用。如果要迁移到
K8s ,则需要对代码库进行修改,以使启动过程更有效,这样用户就不会有糟糕的体验。 -
迁移到无状态需要付出很多努力:如果您的应用程序是群集或无状态的,则不会配置额外的
Pod ,并且必须在应用程序中重新配置。 -
安装过程繁琐:如果您不使用
Azure ,Google 或Amazon 等任何云提供商,则很难在群集上设置K8s ;不过在有Rancher 这样的工具辅助下,安装效率也有了大幅度的提高。
云操作系统
在
简单做个类比:整个集群的计算资源统一管控起来就像一个单机的物理计算资源,容器就像一个个进程,
微服务
现在我们都习惯了使用微服务来构建服务端架构,
API 网关:Ingress- 无状态化:区分有状态与无状态的应用,
K8s 中无状态对应Deployment ,有状态对应StatefulSet - 数据库的横向扩展:
Headless Service 指向PaaS 服务,或者StatefulSet 部署 - 缓存:
Headless Service 指向PaaS 服务,或者StatefulSet 部署 - 服务拆分与服务发现:Service
- 服务编排与弹性伸缩:
Deployment 的Replicas - 统一配置中心:ConfigMap
- 统一的日志中心:
DaemonSet 部署日志Agent - 熔断,限流,降级:Service Mesh
- 全方位的监控:Cadvisor,
DaemonSet 部署监控
Kubernetes、
基础设施使用YAML 表达
从
apiVersion: v1
kind: Pod
metadata:
name: site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
这种表示方式使
-
GitOps 或Git 操作版本控制。使用这种方法,你可以将所有的Kubernetes YAML 文件都保存在git 仓库下,这样你就可以准确地知道何时进行了更改,谁做了更改,以及具体更改了什么。这使得整个组织的透明度更高,并且通过避免团队成员弄不清楚去哪里寻找配置,从而提高了效率。同时,只需合并一个拉动请求,就可以更方便地自动化更改Kubernetes 资源。 -
可扩展性。将资源定义为
YAML ,使得集群操作人员在Kubernetes 资源中改变一两个数字来扩容或者缩容集群。Kubernetes 有水平pod 自动缩放器,可以指定给定部署所需要的最小和最大pod 数量,以便能自动缩容/ 扩容应对流量低谷/ 高峰。例如,如果你正在运行的部署可能因为流量突增而需要更多的容量,你可以将maxReplicas 从10 个改为20 个。
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: myapp
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp-deployment
minReplicas: 1
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
- 安全和控制。
YAML 是验证在Kubernetes 中部署什么和如何部署的好方法。例如,当涉及到安全问题时,一个重要的关注点就是你的工作负载是否以非root 用户的身份运行。我们可以利用像conftest 这样的工具(YAML/JSON 验证器) ,再加上Open Policy Agent 这样的策略验证器,来检查你的工作负载的SecurityContext 是否不允许容器作为root 用户运行。为此,用户可以使用一个简单的Open Policy Agent rego 策略,如下。
package main
deny[msg] {
input.kind = "Deployment"
not input.spec.template.spec.securityContext.runAsNonRoot = true
msg = "Containers must not run as root"
}
- 云供应商的整合。科技行业的主要趋势之一就是在公有云供应商中运行工作负载。在云供应商组件的帮助下,
Kubernetes 允许每个集群与它所运行的云供应商进行集成。例如,如果用户在AWS 中的Kubernetes 中运行某应用程序,并希望该应用程序可以通过服务访问,云供应商会帮助自动创建一个LoadBalancer 服务,该服务会自动提供一个Amazon Elastic Load Balancer 来将流量转发到应用程序的pods 。
可扩展性
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: crontabs.my.org
spec:
group: my.org
versions:
- name: v1
served: true
storage: true
Schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
cronSpec:
type: string
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
replicas:
type: integer
minimum: 1
maximum: 10
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
我们以后可以用如下的方式创建一个
apiVersion: "my.org/v1"
kind: CronTab
metadata:
name: my-cron-object
spec:
cronSpec: "* * * * */5"
image: my-cron-image
replicas: 5
$ operator-sdk new my-operator --repo github.com/myuser/my-operator
这就为你的
.
|____cmd
| |____manager
| | |____main.go
|____go.mod
|____deploy
| |____role.yaml
| |____role_binding.yaml
| |____service_account.yaml
| |____operator.yaml
|____tools.go
|____go.sum
|____.gitignore
|____version
| |____version.go
|____build
| |____bin
| | |____user_setup
| | |____entrypoint
| |____Dockerfile
|____pkg
| |____apis
| | |____apis.go
| |____controller
| | |____controller.go
添加
$ operator-sdk add api --api-version=myapp.com/v1alpha1 --kind=MyAppService
$ operator-sdk add controller --api-version=myapp.com/v1alpha1 --kind=MyAppService
最后构建并推送
$ operator-sdk build your.container.registry/youruser/myapp-operator
如果开发者需要更多的控制权,他们可以修改
另一个项目
$ kubectl kudo install zookeeper
$ kubectl kudo install kafka
然后用另一个命令来调整
$ kubectl kudo install kafka --instance=my-kafka-name \
-p ZOOKEEPER_URI=zk-zookeeper-0.zk-hs:2181 \
-p ZOOKEEPER_PATH=/my-path -p BROKER_CPUS=3000m \
-p BROKER_COUNT=5 -p BROKER_MEM=4096m \
-p DISK_SIZE=40Gi -p MIN_INSYNC_REPLICAS=3 \
-p NUM_NETWORK_THREADS=10 -p NUM_IO_THREADS=20