【云原生】Kubernetes核心技术(下)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: Kubernetes核心技术(下)


博主昵称:跳楼梯企鹅

创作初心:本博客的初心为与技术朋友们相互交流,每个人的技术都存在短板,博主也是一样,虚心求教,希望各位技术友给予指导。
博主座右铭:发现光,追随光,成为光,散发光;
博主研究方向:渗透测试、机器学习 ;
博主寄语:感谢各位技术友的支持,您的支持就是我前进的动力 ;

图片.png

本篇文章分为3次分享完

前两部分已经分享了,今天来完结吧~

七·、Job

图片.png

1.快速了解

Kubernetes jobs主要是针对短时和批量的工作负载。它是为了结束而运行的,而不是像deployment、replicasets、replication controllers和DaemonSets等其他对象那样持续运行。

Kubernetes Jobs会一直运行到Job中指定的任务完成。也就是说,如果pods给出退出代码0,那么Job就会退出。而在正常的Kubernetes中,无论退出代码是什么,deployment对象在终止或出现错误时都会创建新的pod,以保持deployment的理想状态。

在job运行过程中,如果托管pod的节点发生故障,Job pod将被自动重新安排到另一个节点。

2. 实例

(1)批处理任务: 比如说你想每天运行一次批处理任务,或者在指定日程中运行。它可能是像从存储库或数据库中读取文件那样,将它们分配给一个服务来处理文件。

(2)运维/ad-hoc任务: 比如你想要运行一个脚本/代码,该脚本/代码会运行一个数据库清理活动,甚至备份一个Kubernetes集群。

3.创建Kubernetes Job

使用自定义的Docker镜像创建一个job.yaml文件,参数传递给docker ENTRYPOINT脚本。
apiVersion: batch/v1 
使用kubectl创建一个job.yaml文件的job
kubectl apply -f job.yam
使用kubectl检查job的状态
kubectl get jobs
使用kubectl获取pod列表
kubectl get po
使用kubectl获取job pod 日志。使用你在输出中看到的Pod名称替换原本的Pod名称。
kubectl logs kubernetes-job-example-bc7s9 -f
如下输出:
并行运行多Job pods
当一个job被部署后,你可以让它在多个Pod上并行运行:
completions: 6
带有那些参数的manifest:
apiVersion: batch/v1
为Kubernetes Job生成随机名称
你不能从一个job manifest文件中创建多个job
apiVersion: batch/v1

image.gif

4.运行一次性容器

启动这个job
[root@k8s-master k8s]# kubectl apply -f myjob.yml 
job.batch/myjob created
kubectl get job 查看这个job
[root@k8s-master k8s]# kubectl get job
NAME    COMPLETIONS   DURATION   AGE
myjob   1/1           23s        3m45s
completions为 1/1 表示成功运行了这个job
kubectl get pod 查看pod的状态
[root@k8s-master k8s]# kubectl get pod
NAME          READY   STATUS      RESTARTS   AGE
myjob-29qlw   0/1     Completed   0          4m5s
看到 状态为Completed表示这个job已经运行完成
kubectl  logs 命令查看这个 pod的日志
[root@k8s-master k8s]# kubectl logs myjob-29qlw
hello k8s job!

image.gif

5.job controller源码

image.gif图片.png

JobController 结构
type JobController struct {
    // 访问 kube-apiserver 的client
    // 需要查询 job、pod 等元数据信息
    kubeClient clientset.Interface
    // pod 控制器,用于创建和删除pod使用
    podControl controller.PodControlInterface
    // 用于更新 job status
    updateHandler func(job *batch.Job) error
    // job controller 核心接口,用于 sync job
    syncHandler   func(jobKey string) (bool, error)
    // job controller 在启动时会对 job & pod 先进行同步
    // 用于判断是否已经对 pod 同步过
    podStoreSynced cache.InformerSynced
    // 用于判断是否已经对 job 同步过
    jobStoreSynced cache.InformerSynced
    // expectations cache,记录该job下pods的adds & dels次数,
    // 并提供接口进行调整,已达到期望值。
    expectations controller.ControllerExpectationsInterface
    // jobLister 用于获取job元数据及根据pod的labels来匹配jobs
    // 该controller 会使用到的接口如下:
    // 1. GetPodJobs(): 用于根据pod反推jobs
    // 2. Get(): 根据namespace & name 获取job 元数据
    jobLister batchv1listers.JobLister
    // podStore 提供了接口用于获取指定job下管理的所有pods
    podStore corelisters.PodLister
    // Jobs queue
    // job controller通过kubeClient watch jobs & pods的数据变更,
    // 比如add、delete、update,来操作该queue。
    // 并启动相应的worker,调用syncJob处理该queue中的jobs。
    queue workqueue.RateLimitingInterface
    // jobs的相关events,通过该recorder进行广播
    recorder record.EventRecorder
}
startJobController()
func startJobController(ctx ControllerContext) (bool, error) {
    // 在启动job controller之前,判断下job 是否有配置生效
    // 用户可以在创建k8s clusters时,通过修改kube-apiserver --runtime-config配置想要生效的 resource
    if !ctx.AvailableResources[schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"}] {
        return false, nil
    }
    // 初始化 JobController结构,并Run
    // Run的时候指定了gorutinue的数量,每个gorutinue 就是一个worker
    go job.NewJobController(
        ctx.InformerFactory.Core().V1().Pods(),
        ctx.InformerFactory.Batch().V1().Jobs(),
        ctx.ClientBuilder.ClientOrDie("job-controller"),
    ).Run(int(ctx.ComponentConfig.JobController.ConcurrentJobSyncs), ctx.Stop)
    return true, nil
}
NewJobController()
func NewJobController(podInformer coreinformers.PodInformer, jobInformer batchinformers.JobInformer, kubeClient clientset.Interface) *JobController {
    // 初始化event broadcaster
    // 用于该controller 发送job 相关的events
    eventBroadcaster := record.NewBroadcaster()
    // 注册打印event信息的function
    // eventBroadcaster.StartEventWatcher()会创建gorutinue并开始watch event,
    // 根据注册的eventHandler轮询处理每个event,这里就是通过glog.Infof打印日志
    eventBroadcaster.StartLogging(glog.Infof)
    // EventSinkImpl 包含了一个EventInterface, 实现了Create/Update/Delete/Get/Watch/Patch..等等操作
    // 这一步跟上面一样,也是通过eventBroadcaster.StartEventWatcher() 注册了EventInterface实现,
    // 用来从指定的eventBroadcaster接收event,并发送给指定的接收器。
    // k8s event实现可以多带带进行源码分析,值得学习下。
    eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")})
    // kubernetes 内部的限流策略
    // 对apiserver来说,每个controller及scheduler都是client,所以内部的限流策略也至关重要。 
    if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil {
        metrics.RegisterMetricAndTrackRateLimiterUsage("job_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter())
    }
    // 初始化JobController
    jm := &JobController{
        // 连接kube-apiserver的client
        kubeClient: kubeClient,
        // podControl,用于manageJob()中创建和删除pod
        podControl: controller.RealPodControl{
            KubeClient: kubeClient,
            Recorder:   eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "job-controller"}),
        },
        // 维护的期望状态下的Pod Cache,并且提供了修正该Cache的接口
        // 比如会存jobs 下pods 的adds & dels 值,并提供了接口修改这两个值。
        expectations: controller.NewControllerExpectations(),
        // jobs queue, 后面会创建对应数量的workers 从该queue 中处理各个jobs。
        queue:        workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(DefaultJobBackOff, MaxJobBackOff), "job"),
        // event recorder,用于发送job 相关的events
        recorder:     eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "job-controller"}),
    }
    // 注册jobInformer 的Add、Update、Delete 函数
    // 该controller 获取到job 的Add、Update、Delete事件之后,会调用对应的function
  // 这些function 的核心还是去操作了上面的queue,让syncJob 处理queue 中的jobs
    jobInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
        AddFunc: func(obj interface{}) {
            jm.enqueueController(obj, true)
        },
        UpdateFunc: jm.updateJob,
        DeleteFunc: func(obj interface{}) {
            jm.enqueueController(obj, true)
        },
    })
    // 上面结构中已经有介绍
    jm.jobLister = jobInformer.Lister()
    jm.jobStoreSynced = jobInformer.Informer().HasSynced
    // 注册 podInformer 的Add、Update、Delete 函数
  // job 最终是依托了pod 去运行,所以相关的pods 事件也需要关心。
  // 该podInformer 会监听所有的pods 变更事件,所以函数中都会去判断该pod 的containerRef是否是“job”,
    // 如果是的话再更新对应的expectations & queue, 触发syncJob进行处理。
    podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
        AddFunc:    jm.addPod,
        UpdateFunc: jm.updatePod,
        DeleteFunc: jm.deletePod,
    })
    // 上面结构中已经有介绍
    jm.podStore = podInformer.Lister()
    jm.podStoreSynced = podInformer.Informer().HasSynced
    // 注册更新job status的函数
    jm.updateHandler = jm.updateJobStatus
    // 注册sync job handler
    // 核心实现
    jm.syncHandler = jm.syncJob
    return jm
}
Run()
// Run the main goroutine responsible for watching and syncing jobs.
func (jm *JobController) Run(workers int, stopCh <-chan struct{}) {
    defer utilruntime.HandleCrash()
    defer jm.queue.ShutDown()
    glog.Infof("Starting job controller")
    defer glog.Infof("Shutting down job controller")
    // 每次启动都会先等待Job & Pod cache 是否有同步过,即指queue是否已经同步过数据,
    // 因为每个worker干的活都是从queue中获取,所以只有queue有数据才应该继续往下创建worker。
    if !controller.WaitForCacheSync("job", stopCh, jm.podStoreSynced, jm.jobStoreSynced) {
        return
    }
    // 创建指定数量的gorutinue
    // 每个gorutinue 执行worker,每个worker 执行完了之后sleep 1s,然后继续循环执行
    for i := 0; i < workers; i++ {
        go wait.Until(jm.worker, time.Second, stopCh)
    }
    <-stopCh
}

image.gif

6.cronJob

cronJob是基于时间进行任务的定时管理:

在特定的时间点运行任务

反复在指定的时间点运行任务:比如定时进行数据库备份,定时发送电子邮件等等。

八、ConfigMap

   为了解决传统容器中配置的挂载、变更、管理等问题,在k8s中引入了一个叫做configmap的资源对象,在configmap中,各个配置项都是以key-value的方式存在的,value的数据可以是一个配置文件的内容,这些配置项被保存在k8s使用的持久化存储etcd中。这样就形成了一个k8s中的配置中心,可以独立的对configmap中的数据进行修改,然后将configmap挂载到pod中进行使用,可以以env的方式,也可以以配置文件的方式在pod中进行引用,这样配置和pod就实现了解耦,都是k8s中独立的资源对象。

个人理解:configmap是k8s中的应用配置管理方案。

image.gif图片.png

1. ConfigMap基础命令

kubectl create configmap test --from-file=/root/yaml/nginx.yaml 
#将/root/yaml/nginx.yaml文件写入configmap  名字为test(存储配置文件)
kubectl create configmap test02 --from-file=/root/yaml/
#将/root/yaml/目录下的文件写入configmap,configmap 名字为test02
kubectl create configmap test01 --from-literal=MYSQL_ROOT_PASSWORD=123456
#变量储存到configmap,变量名为MYSQL_ROOT_PASSWORD,值为123456,可以跟更多变量,在尾部加--from-literal=key=value  即可
kubectl describe configmaps test
#查询上面的结果

image.gif

2. configmap对象

(1)定义环境变量

kubectl apply -f - <<'eof'
apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-vars
data:
  apploglevel: info
  appdatadir: /var/data
eof

image.gif

(2)执行创建configmap

[root@root ~]# kubectl apply -f - <<'eof'
> apiVersion: v1
> kind: ConfigMap
> metadata:
>   name: cm-vars
> data:
>   apploglevel: info
>   appdatadir: /var/data
> eof
configmap/cm-vars created
[root@root ~]# kubectl get cm
NAME               DATA   AGE
cm-vars            2      5s
kube-root-ca.crt   1      38d
[root@root ~]#

image.gif

(3)查看configmap

[root@root ~]# kubectl get cm cm-vars -o yaml
apiVersion: v1
data:
  appdatadir: /var/data
  apploglevel: info
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"appdatadir":"/var/data","apploglevel":"info"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"cm-vars","namespace":"default"}}
  creationTimestamp: "2022-01-10T07:31:05Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:appdatadir: {}
        f:apploglevel: {}
      f:metadata:
        f:annotations:
          .: {}
          f:kubectl.kubernetes.io/last-applied-configuration: {}
    manager: kubectl-client-side-apply
    operation: Update
    time: "2022-01-10T07:31:05Z"
  name: cm-vars
  namespace: default
  resourceVersion: "11021769"
  selfLink: /api/v1/namespaces/default/configmaps/cm-vars
  uid: c513d39b-c128-46d3-9eb7-78da20ec47f2
[root@root ~]# kubectl describe cm cm-vars
Name:         cm-vars
Namespace:    default
Labels:       <none>
Annotations:  <none>
Data
====
appdatadir:
----
/var/data
apploglevel:
----
info
Events:  <none>

image.gif

(4)使用configmap

apiVersion: v1
kind: ConfigMap
metadata:
  name: test04
data:
  MYSQL_ROOT_PASSWORD: '123456' 
  #定义一个变量,值类型为字符串,所以需要加引号
  my.cnf: |
    [mysqld]
    pid-file                        = /var/run/mysqld/mysqld.pid
    socket                          = /var/run/mysqld/mysqld.sock
    datadir                         = /var/lib/mysql
    character-set-server            = utf8
    log-error                       = /var/log/mysqld.log
    # 中继日志
    relay-log=mysql-relay-bin
    replicate-wild-ignore-table=mysql.%
    replicate-wild-ignore-table=test.%
    replicate-wild-ignore-table=information_schema.%
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /opt    #挂载到那个目录
              name: test
          command:
          - sh
          - -c
          - sleep 100
      volumes:
        - name: test  #存储卷的名称
          configMap:
            name: test04     #configmap名字
            items:
              - key: my.cnf   #configmap 内文件
                path: my.cnf   #configmap挂载到容器内的相对路径

image.gif

九、Secrets

secret是k8s中用来存储敏感认证信息的一种重要资源,大致可以分为三种类型:docker-registrygenerictls,从名称上就可以看出来,分别用于存储镜像仓库认证信息,一般信息和证书信息。其中generic类型的最常用,比较典型的就是用来存放数据库的认证信息。

说白了就是一种安全机制

1.Secret 有三种类型

(1)Service Account :用来访问 Kubernetes API,由 Kubernetes 自动创建,用于被 serviceaccount 引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。

(2)Opaque :base64编码格式的Secret,用来存储密码、密钥等

(3)kubernetes.io/dockerconfigjson :用来存储私有 docker registry 的认证信息

2.创建secret

[root@root pod]# kubectl create secret --help
Create a secret using specified subcommand.
Available Commands:
  docker-registry Create a secret for use with a Docker registry
  generic         Create a secret from a local file, directory or literal value
  tls             Create a TLS secret
Usage:
  kubectl create secret [flags] [options]
Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all
commands).

image.gif

图片.png

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
10天前
|
监控 Cloud Native 持续交付
构建未来:云原生技术驱动的云计算平台
【5月更文挑战第52天】 随着数字化转型的不断深化,企业对于敏捷性、可扩展性和成本效益的需求日益增长。本文探讨了如何通过采纳云原生技术来构建和优化云计算平台,以支持不断变化的业务需求。文章首先概述了云原生技术的核心概念及其优势,随后详细分析了在设计云平台时应考虑的关键要素,并通过案例研究展示了云原生实践在实际中的应用效果。最后,文章提出了面向未来的云平台发展趋势和挑战。
|
6天前
|
人工智能 运维 Cloud Native
活动回顾丨云原生技术实践营 Serverless + AI 专场 (深圳站) 回顾 & PPT 下载
云原生技术实践营 Serverless + AI 专场 (深圳站) 回顾。
|
3天前
|
Kubernetes Cloud Native 持续交付
云原生技术的演变与未来趋势
在数字化转型的浪潮中,云原生技术成为推动现代软件开发、部署和运营的关键力量。本文将深入探讨云原生技术从诞生到成熟的过程,分析其在当前企业中的应用现状,并预测未来的发展趋势。通过引用最新的行业报告和科学研究,文章旨在为读者提供对云原生技术演进的深刻见解,并揭示其对企业IT架构的长远影响。
|
11天前
|
人工智能 运维 Cloud Native
云端融合:探索云原生技术的未来趋势
【6月更文挑战第19天】 在数字化时代的浪潮中,云原生技术如同一颗耀眼的星辰,引领着软件开发和运维的新方向。本文将深入探讨云原生技术的核心概念、优势以及面临的挑战,并通过案例分析展现其在实际应用中的成效。我们将一窥云原生技术如何推动企业IT架构的现代化转型,以及它在未来可能带来的行业变革。
|
8天前
|
运维 Cloud Native 开发者
云原生技术演进:从微服务到无服务器计算
【6月更文挑战第22天】 云原生技术如同一场持续的演化之旅,它不断重塑着应用的开发与部署方式。本文将探讨云原生技术如何从微服务架构演变至无服务器计算,以及这一转变对开发者和运维人员带来的深远影响。通过分析容器化、持续集成/持续部署(CI/CD)、微服务治理等关键概念,我们将揭示云原生技术如何在提高应用的可伸缩性、灵活性和可靠性的同时,也提出了新的挑战和机遇。
|
5天前
|
运维 Cloud Native 持续交付
云原生技术在现代企业中的应用与挑战
云原生技术,作为一种新兴的云计算范式,正在引领着企业IT架构的变革。它的核心在于构建和运行可弹性扩展的应用程序,充分利用云平台的灵活性和可扩展性。然而,云原生技术的引入并非一帆风顺,企业在享受其带来的便利的同时,也面临着一系列挑战。本文将从云原生技术的定义、优势、应用场景以及面临的挑战等方面进行探讨,旨在为企业在云原生转型过程中提供参考和借鉴。
|
7天前
|
运维 Cloud Native 持续交付
云原生技术的崛起与应用前景
在当今快速发展的科技领域中,云原生技术作为一种革命性的开发和部署方式,正以其灵活性和效率优势改变着软件开发和运维的面貌。本文将探讨云原生技术的定义、关键特性以及在现代软件开发中的应用前景,旨在帮助读者深入理解这一新兴技术的重要性和实际价值。
18 3
|
7天前
|
人工智能 Cloud Native Serverless
云原生技术实践营 · 深圳站:Serverless + AI 专场开启报名!
“云原生技术实践营 · 深圳站 ——Serverless + AI 应用开发专场”是一场以 Serverless 为主题的技术活动,通过一个下午的时间增进对 Serverless 技术的理解,快速上手,活动受众以关注 Serverless 技术的开发者、企业决策人、云原生领域创业者为主,活动形式为演讲、动手实操。
|
11天前
|
Cloud Native 持续交付 云计算
云原生技术在现代企业中的应用与挑战
【6月更文挑战第19天】随着云计算技术的飞速发展,云原生作为一种新兴的构建和运行应用程序的方法,正逐步成为推动企业数字化转型的重要力量。本文将深入探讨云原生技术的核心概念、优势以及在实际企业应用中遇到的挑战,同时结合案例分析,展示云原生如何在提升业务敏捷性、降低运营成本及增强系统可靠性方面发挥关键作用。
|
11天前
|
运维 Cloud Native 持续交付
云原生技术:现代应用开发的革命性变革
云原生技术正在重新定义软件开发和部署的方式。通过采用容器、微服务、持续集成与持续交付(CI/CD)等关键技术,企业可以显著提升开发效率、缩短上市时间,并提高应用的可扩展性和可靠性。本文深入探讨了云原生技术的核心组件及其带来的实际业务价值,展示了其在现代应用开发中的革命性影响。
13 1

热门文章

最新文章