16.实践篇:让我们聊一聊运维利器(三):Operator控制器
16.实践篇:让我们聊一聊运维利器(三):Operator控制器
1.为什么还需要Operator?
我们前面讲了很多很多基础的资源对象和控制器,如pod、deployment、service、deployment等等,仿佛已经满足了我们大多数情况的场景和需求了,那我们为什么还需要operator呢?
我们再来回顾一下,无状态应用(如nginx)的扩容是最方便的,我们只要使用deployment控制器中的ReplicaSet字段申明,我们需要几个数量的nginx节点即可。
那对于有状态应用呢?
此时你可能想到,StatefulSet控制器,没错!他的确能够帮助我们解决有状态应用基础的扩缩容动作和行为逻辑,但是还有大多数场景,他是完成不了的。
如mysql主从集群、多主集群的扩缩容、备份、数据迁移等包含一系列传统架构中,需要运维人员介入,并通过脚本处理的复杂操作。
另外,在Kubernetes上运维人员通常喜欢使用自动化来处理重复的任务。
Operator控制器就是将运维人员的知识、操作和预期翻译成代码片段,如果你了解jenkins,就好比jenkins file、DSL和groovy。
这是我一直坚信和推崇的一个理念:“基础设施即代码”(Infrastructure as Code)
正是如此,他们每个节点具有不同的角色配置文件、启动顺序、依赖性和自动化操作。此时,StatefulSet控制器已经胜任不了了,Operator就此诞生!
2.What is Operator?
Operator由CoreOS开发的,通过软件的方式进行扩展kubernetes。Operator通过使用CRD(自定义资源)来管理他们各有应用和基础组件。
CRD(CustomResourceDefinition):通过扩展kubernetesAPI,从而满足用户的定制化需求。我们后面会具体讲解
同时,Operator也遵循了kubernetes的原理、尤其是控制循环。
注意:Operator的开发和维护工作,并不属于kubernetes本身,而是在于各产品线(mysql、jenkins、prometheus等等)。他们才是致力于维护各自Operator的主角,并帮助用户快速在kubernetes集群上搭建、维护和高效使用自己的产品。
3.Operator原理
Operator通过扩展Kubernetes定义Custom Controller,观察应用并根据实际状态执行自定义任务。应用被定义为Kubernetes对象:Custom Resource (CR),它包含yaml spec和被API服务接受的对象类型。如图所示,Operator控制器的调度逻辑和以往原生控制器调度的逻辑有以下的不同点:
1.Operator通过Custom Controller协调应用的spec属性,原生控制器则通过kubelet;
2.Operator可以独立运行在集群内部或外部,原生控制器则必须运行于集群内部。
Operator控制器真正价值来自于你对应用失败状态处理的最佳实践,以及Operator如何协同人工干预的期望逻辑。
4.Operator应用场景
如果有以下涉及的工作内容刚需,你可以选择operator来帮助你:
1>按需部署应用程序
2>获取并恢复应用程序状态的备份数据
3>处理应用程序升级相关的变更需求,如数据库库表,或者是额外事项的配置
4>发布一个服务,使得原本kubernetes API原生不支持的应用可以发现它
5>模拟整个或部分集群中的故障以测试其弹性
6>在没有内部成员选举程序的情况下,为分布式应用程序选择一位领导者
5.如何部署Operator
我们部署Operator最常见也是最通用的方法就是,在我们的kubernetes集群中,新增相应的CRD资源,以及和他相关联的控制器。
这个控制器通常运行于控制平面(https://kubernetes.io/docs/reference/glossary/?all=true#term-control-plane)之外。
这里我还整理了两个市面上主流的Operator资源社区,供你实践时参考使用:
operatorhub.io(https://operatorhub.io/)
awesome-operators(https://github.com/operator-framework/awesome-operators)
6.如何使用Operator
通过上面我提供的2个地址,你可以找到自己所需的Operator资源。你可以通过一系列的帮助和文档,可能会经历一些坎坷,完成你的第一个Operator的部署工作。一旦你部署完成,你就可以像使用原生kubernetes控制器的方法来操作他了,如:get、delete等方法。不同的是,每个Operator都有各自特有的类型(kind),如下所示:
#mysql operator的常用操作 kuberctl get mysql kuberctl edit mysql/mysql-1
7.实战:部署一个Jenkins Operator(v0.3.x)
操作之前,你需要make sure确保以下两点:
1.access to a Kubernetes cluster version 1.11+
2.kubectl version 1.11+
7.1.What's the Jenkins Operator?
jenkins operator是kubernetes平台上原生的,可以全面管理jenkins的控制器,以代码既配置的思想为基础,目前提供了以下几点功能:
1>与kubernetes集成
2>pipelines as code
3>通过groovy脚本配置进行扩展
4>安全和配置增强
7.2.功能现状
但operator也有不少问题待解决,一些是本身的缺陷,还有一些则是传统架构下jenkins遗留的不足之处:
1>安装具有不兼容版本或安全漏洞的插件
2>更好的配置作为代码思想
3>安全和开箱即用的特性
4>使错误对终端用户更明显
5>备份和还原作业历史记录
6>优雅关闭的处理
7>生命周期内端到端的测试
7.3.环境安装
1)首先,我们来部署专有的CRD资源
kubectl apply -f https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/deploy/crds/jenkins_v1alpha2_jenkins_crd.yaml
你可以不难发现,Jenkins Operator有特有的kind名称:jenkins.jenkins.io,并且是名称空间级别的资源。
apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: jenkins.jenkins.io spec: group: jenkins.io names: kind: Jenkins listKind: JenkinsList plural: jenkins singular: jenkins scope: Namespaced versions: - name : v1alpha2 served: true storage: true - name : v1alpha1 served: true storage: false
2)接下来,我们要创建名为jenkins-operator的ServiceAccount、role名为jenkins-operator的RBAC策略、镜像为virtuslab/jenkins-operator:v0.3.1、并且运行在default名称空间中。
kubectl apply -f https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/deploy/all-in-one-v1alpha2.yaml
如果碰到镜像拉取失败的情况,你可以在Jenkins_docker_hub(https://hub.docker.com/r/virtuslab/jenkins-operator)获取相关镜像。
3)此时,你可以通过命令kubectl get pods -w观察pod资源的生成情况了。
jenkins-operator-7768f7c484-rhnhz 0/1 Pending 0 0s jenkins-operator-7768f7c484-rhnhz 0/1 Pending 0 0s jenkins-operator-7768f7c484-rhnhz 0/1 ContainerCreating 0 0s jenkins-operator-7768f7c484-rhnhz 1/1 Running 2 76s
7.4.部署Jenkins
1)Jenkins Operator我们已经部署并运行起来了,接下来我们要运行一个实际的本地jenkins实例。
apiVersion: jenkins.io/v1alpha2 kind: Jenkins metadata: name: example spec: master: containers: - name: jenkins-master image: jenkins/jenkins:lts imagePullPolicy: Always livenessProbe: failureThreshold: 12 httpGet: path: /login port: http scheme: HTTP initialDelaySeconds: 80 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 5 readinessProbe: failureThreshold: 3 httpGet: path: /login port: http scheme: HTTP initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 resources: limits: cpu: 1500m memory: 3Gi requests: cpu: "1" memory: 500Mi seedJobs: - id: jenkins-operator targets: "cicd/jobs/*.jenkins" description: "Jenkins Operator repository" repositoryBranch: master repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
这里有个坑:pod初始化的时候会去下载很多插件,探针的初始检查时间为80秒;你要视本身网络情况调整initialDelaySeconds字段的值;或者通过squid等代理的方式进行规避。
2)你可以通过以下命令申明,并观察相关资源的生成。
#声明我们的配置文件 kubectl apply -f jenkins_instance.yaml #观察pod情况 kubectl get pods -w
3)你可以通过以下命令获取登录所需的用户名和密码信息。
kubectl get secret jenkins-operator-credentials-example -o 'jsonpath={.data.user}' | base64 -d kubectl get secret jenkins-operator-credentials-example -o 'jsonpath={.data.password}' | base64 -d
4)接下来我们连上jenkins就可以了,此时你就可以在本地的localhost:8080访问jenkins的登录页面了。
minikube:
minikube service jenkins-operator-http-<cr_name> --url
kubelet:
kubectl port-forward jenkins-<cr_name> 8080:8080
其他具体的配置功能,你可以参考configuration。
@版权声明:51CTO独家出品,未经允许不能转载,否则追究法律责任