kubernetes 学习实践 -- pod

云原生现在是炙手可热的技术,而这里面最核心的当属大名鼎鼎的Kubernetes;K8S号称是未来时代的操作系统,是云原生时代IT工程师必备的技能。

学习应当有输出,下面是对pod相关知识的学习


pod 的一些基础概念:

pod是K8S中最小的调度单位,那么为啥不是docker容器呢?答案可能是从最开始K8S就没有将容器作为架构的核心,正如K8S的前身--Google的Borg系统研究人员提出的:

运行在大规模集群中的各种任务之间,实际上存在各种各样的关系。这些关系的处理,才是作业编排和管理系统最困难的地方

pod扮演的是传统部署环境中“虚拟机”的角色,而容器则是这个“虚拟机”中运行的用户程序。

pod只是一个逻辑概念,K8S真正处理的是宿主机OS上容器的namespace和cgroups,并不存在所谓的pod边界或者隔离,pod内部是有一个infra容器存在的,它是pod内的第一个容器。

infra容器是一个用汇编语言编写的,永远处于“暂停”状态的容器,大小只有几百KB,举例:

image

pod的生命周期,只跟其内部的infra容器有关系,而与其他容器无关;infra容器永远是第一个被创建的容器

pod是一组共享了某些资源的容器,这些容器可共享的资源有: 网络namespace、pv卷、security context

用户定义的容器,则可通过join network namespace的方式与infra容器关联一起;对同一个pod里的所有用户来讲,进出的流量都可认为是通过infra容器完成的。

对于volume,K8S只需要把volume的定义设计在pod层级即可,一个volume对应的宿主机目录对于pod来说就只有一个,pod里的容器只要声明挂载这个volume,就可以共享这个volume对应的宿主机目录。

pod内部容器之间的超亲密关系,形成了sidecar模式,即容器设计模式,常见的场景包括日志收集、通信适配等,而这也是service mesh项目如istio微服务治理的原理。

pod相关的属性:

pod级别的属性应该是如下所描述的属性:

  • 和调度、网络、存储、安全相关的属性
  • 和容器linux namespace相关的属性
  • 容器要共享宿主机的namespace,也一定是pod级别的定义

pod的四大类属性(应该是API对象的四大类属性),及每个大类里常见的子属性:

  • typemeta: 最基本的定义
    • Group
    • Kind
    • Version
  • metadata:内有2个最重要的属性,即namespace和name,它俩可唯一确定某个对象实例;其余常见的字段还有
    • Label
    • Annotation
    • Finalizer
    • ResourceVersion
  • spec : 核心属性,每个对象独有,用户的期望状态,由创建对象的用户端来定义
  • status : 核心属性,每个对象独有,对象的实际状态,由对应的控制器收集状态并更新

pod的status状态:

  • pending :api对象已创建在etcd中,pod里的有些容器因为某种原因无法顺利创建

  • running :至少有一个容器已经在运行了

  • succeeded :pod里的所有容器都跑完且退出,在运行job任务时常见

  • failed :至少有一个容器是不正常的状态

  • unknown :异常状态,pod状态无法被kubelet汇报给kube-apiserver,比如从节点挂了

  • CrashLoopBackOff :比如拉镜像失败

对于pod的状态并不需要死记硬背,记住下面两个原理即可:

  • 只要pod的restartPolicy指定的策略允许重启异常容器(eg:always),那么这个pod就会保持running状态,并进行容器重启; 否则就会进入failed状态

  • 对于包含多个容器的pod,只有它里面所有容器都进入异常状态,pod才会进入failed状态;在此之前pod都是running状态,且此时ready字段会显示正常容器个数

一些命令与操作:

  • 首先可以设置kubectl命令别名,因为它实在有点长:
    alias k=kubectl

  • 通过explain可以获取字段的详细解释,可以快速了解对象字段的意义:
    k explain xxx

root@ubuntu:/home/kubeyaml# k explain pods
KIND:     Pod
VERSION:  v1

DESCRIPTION:
     Pod is a collection of containers that can run on a host. This resource is
     created by clients and scheduled onto hosts.

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
  ...

并且可以指定下层属性:

root@ubuntu:/home/kubeyaml# k explain pods.apiVersion
KIND:     Pod
VERSION:  v1

FIELD:    apiVersion <string>

DESCRIPTION:
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
  • 获取已创建pod的完整信息,可以选择是yaml或json格式:

k get pod name -o yaml/json

  • label相关

label可以附加到任何K8S对象上,不仅仅是pod

修改现有pod的label:
k label po nginx app=label1

如果修改的是已经存在的label,要加上--overwirte参数:
k label po nginx app=label1 --overwrite

删除label:
k label po nginx app- (后边带一个 - 号)

获取pod有哪些label:
k get pod xx --show-labels

只对某些label感兴趣,可以指定-L参数指定它们,如果label不存在,这一列就会为空:
k get pod -L app,bpp

root@ubuntu:/home/kubeyaml# k get po curl-custom-ambassador -L app,bpp,cpp
NAME                     READY   STATUS    RESTARTS   AGE   APP      BPP      CPP
curl-custom-ambassador   2/2     Running   29         62d   label1   label2   

使用label选择器列出想要的 pod,超多写法:
k get po -l xx=yy (找出带有xx标签,且值等于yy的pod)
k get po -l xx!=yy (选择带有xx标签,且值不等于yy的pod)
k get po -l xx (选择带有xx标签的pod)
k get po -l '!xx' (注意单引号)
k get po -l env in (prod,dev)
k get po -l env not in (prod,dev)
k get po -l env=prod,app=label1 (多个标签的情况,全部匹配才算成功)

  • 注解
    注解也是键值对的形式,与label不同的是,注解并不是为了保存标识信息而存在,它们不能像标签一样用于对象分组;注解的目的主要是为了添加说明,比如指定创建对象的人员姓名,可以让集群中的工作人员之间协作更便利。

添加注解:
k annotate pod xx mycompany.com/somenot="foo bar"
同样的,如果想覆盖之前的注解,可添加--overwrite参数

查看刚刚添加的注解:
k describe po curl-custom-ambassador | grep Annotation

root@ubuntu:~# k describe po curl-custom-ambassador | grep Annotation
Annotations:  mycomp.com/somenot: foo bar
  • namespace

创建一个namespace,可以不用yaml文件,直接用命令:
k create namespace xxxx
不同namespace中的pod对象是可以重名的。
大多数对象的名称必须符合RFC1035域名规定的命名规范,即只能包含字母、数字、横杠-,点号,但namespace中是不能有点号的。

如何快速切换到不同的namespace:
alias kcd='kubectl config set-context $(kubectl config current-context) --namespace'
然后,就可以使用 kcd some-namespace在namespace之间快速切换
举例,先切换到my这个namespace下,查看pod,发现是空的

root@ubuntu:~# kcd my
Context "minikube" modified.
root@ubuntu:~# k get po
No resources found in my namespace.

然后切到default namespace下,pod又出现了

root@ubuntu:~# kcd default
Context "minikube" modified.
root@ubuntu:~# k get po
NAME                                            READY   STATUS             RESTARTS   AGE
curl-custom-ambassador                          2/2     Running            31         62d
grafana-69855b9d58-5g86k                        1/1     Running            11         56d
prometheus-alertmanager-998d6d5f8-kkhz7         2/2     Running            22         56d

可以通过-A参数来快速查询所有namespace下的资源,例如:
k get po -A

  • 删除操作

通过标签选择器删除:
k delete po -l xx=yy
删除namespace时,其下的所有pod也会被删除:
k delete ns xx
也可以只删除namespace下的所有pod,保留namespace:
k delete po --all
当然可以更暴力一些:
k delete all --all
此时该namespace下绝大部分的资源类型的实例,都将会删除,比如pod,rc,rs等;也有一些资源此时不会删除,比如secret

  • 保持pod的健康---存活探针

存活探针 liveness probe (还有就绪探针readiness probe, 他们俩的使用场景完全不一样)
1. 当pod调度到某个node,该node上的kubelet就会运行该pod;如果容器的主进程崩溃,kubelet就会重启容器。
2. 即使进程没有崩溃,比如JVM发生了OOM,进程依然可以运行,但此时希望能有办法向K8S发送信号。
3. 当应用死循环或者死锁,就会停止响应,为了确保程序此时可以重启,应当从外部检查应用的情况,而不是依赖程序内部的检测

存活探针的3种机制:

  1. HTTP GET,通过get请求的响应码来判断是否要重启容器
  2. tcp套接字,与容器指定端口建立tcp连接,如果建立不成功则重启容器
  3. exec, 在容器内执行任意命令,并检查命令的退出码

存活探针中重要的附加属性:

  1. timeoutSeconds: 容器必须在这个时间值内做出响应,否则就被认为失败,默认为1s
  2. periodSeconds: 多长时间探测一次,默认10s
  3. failureThreshold: 连续探测 x 次失败之后,重启容器,默认为1
  4. successThreshold: 连续探测 x 次成功之后才算成功,默认为1
  5. initialDelaySeconds: 初始延迟,务必设置,如果不设置,探针会在容器启动时立即开始探测,默认为0
livenessProbe:
  httpGet:
    path: /
    port: 8080
  initialDelaySeconds: 15

在生产中的pod,一定要定义存活探针;如果没有定义,k8s是不会知道应用是否还活着的。

一些推荐的做法:

  1. 确保探针的请求端点不需要认证,比如/health,否则探测会一直失败
  2. 要检查程序内部的状态(从内部对运行的所有重要组件执行状态检查),而不受到外部因素的影响。例如,当web服务器无法连接到后端数据库时,web服务器的存活探针不应该返回失败;因为如果问题是出在数据库,重启web服务器不会解决问题的。
  3. 保持探针轻量,因为探测器执行频率相对较高,探针的CPU时间会计入容器的CPU时间配额,过重的探针会影响容器的运行
  4. 不要在探针中实现重试循环,k8s本身会进行若干次的尝试

参考内容:

极客时间《深入剖析kubernetes》
《Kubernetes in action中文版》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341