0
点赞
收藏
分享

微信扫一扫

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

本篇文章分为3次分享完

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

七·、Job

1.快速了解

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

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!

5.job controller源码

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
}

 6.cronJob

八、ConfigMap

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

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

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
#查询上面的结果

2. configmap对象

(1)定义环境变量

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

 (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 ~]# 

 (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>

 (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挂载到容器内的相对路径

九、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).

  

举报

相关推荐

0 条评论