K8S in Action

1,容器的概念
镜像
镜像仓库
容器

镜像层:Docker镜像由多层构成。好处:网络分发效率,减少镜像的存储空间

1.2 k8s
主节点 ,它承载着 Kubernetes 控制和管理整个集群系统的控制面板
工作节点,它们运行用户实际部署的应用

控制面板
用于控制集群并使它工作,包括:
Kubernetes API 服务器,你和其他控制面板组件都要和它通信
Scheculer ,它调度你的应用
Controller Manager,它执行 群级别的功能,如复制组件、持续跟踪工作节点处理节点失败
etcd ,一个可靠的分布式数据存储,它能持久化存储集群配置

工作节点
是运行容器化应用的机器;
Docker 、rkt或其他的容器类型
Kubelet ,它与 API 服务器通信,并管理它所在节点的容器
Kubernetes Service Proxy (kube proxy ,它负责组件之间的负载均衡网络流量

第一章

linux 容器技术特点:

容器隔离
开销小
进程仍运行在宿主机操作系统,但与其他进程隔离,共用系统内核
轻量

容器隔离机制:
第一个是 Linux 命名空间,它使每个进程只看到它自;
第二个是Linux 控制组 (cgroups),它限制了进程能使用的资源量 (CPU、 内存、 网络带宽等)己的系统视图(文件、进程、网络接口、主机名等);

以下命名空间:
Mount Cmnt)
Process ID (pid)
Network (net)
Inter-process communicaion (ipd)
UTS
User ID (user)

限制资源:
cgroups 是一个 Linux 内核功能, 它被用来限制一个进程或者一组进程的资源使用。
一个进程的资源(CPU、 内存、 网络带宽等)使用量不能超出被分配的量

k8s 集群架构
主节点:承载 着Kubernetes 控制和管理整个集群系统的控制面板
工作节点:运行用户实际部署的应用

主节点控制面板作用:
• Kubernetes API 服务器,你和其他控制面板组件都要和它通信
• Scheculer ,它调度你的应用(为应用的每个可部署组件分配一个工作节点〕
• Controller Manager,它执行集群级别的功能,如复制组件、持续跟踪工作节点处理节点失败
• etcd ,一个可靠的分布式数据存储,它能持久化存储集群配置

工作节点:
docker rtk 等其他容器类型
Kubelet ,它与 API 服务器通信,并管理它所在节点的容器
Kubernetes Service Proxy (kube proxy ,它负责组件之间的负载均衡网络流量

k8s 好处:
简化应用部署
更好的利用硬件
健康检查和自我修复
自动扩容

第二章 开始使用k8s 和docker

镜像是如何构建的:
将整个目录的文件上传到Docker守护进程并在那里进行的,
Docker客户端和守护进程不要求在同一 台机器上

镜像分层:
构建镜像时,Dockerfile 中每一条单独的指令都会创建一个新层

k8s 集群:
kubectl 命令行客户端向运行在主节点上的 Kubemetes API 服务器发出 REST 请求以与集群交互

kubectl 设置补全
vim  ~/.bashrc
alias   k=kubectl 

$ kubectl desc<tab>  no<tab>   gke-ku<tab>

安装bashcompletion  包

pod:
通常一个pod 内包含任意数量的容器。容器内部的进程绑定到指定的端口
pod 有自己独立的私有 IP地址和主机名。

ReplicationController:
用于复制 pod (即创建 pod 的多个副本)并让它们保持运行,如果pod 消失,RC 将创建新的pod

服务:
pod 的存在是短暂的, 一个 pod 可能会在任何时候消失,或许因为它所在节点发生故障, 或许因为有人删除了 pod, 或者因为 pod 被从 一
个健康的节点剔除了。
当其中任何一种情况发生时, 如前所述, 消失的 pod 将被Replication Con tro I !er 替换为新的 pod。
新的 pod 与替换它的 pod 具有不同的 IP地址。服务解决不断变化的pod ip ,以及在一个固定的IP 和端口对上对外暴露多个 pod

当一个服务被创建时, 它会得到一个静态的 IP, 在服务的生命周期中这个 IP不会发生改变。 客户端应该通过固定 IP地址连接到服务, 而不是直接连接 pod

服务表示一组或多组提供相同服务的 pod 的静态地址。 到达服务 IP 和端口的请求将被转发到属于该服务的一个容器的 IP 和端口。

水平伸缩:
水平增加运行实例数
kubectl get replicationcontrollers

增加期望的副本数:
$ kubectl scale rc kubia --replicas=3

kubectl get rc 看副本数
kubectl get pods 查看pod 数

查看pod 运行在哪个节点
kubectl get pods -o wide

第三章 pod

一个 pod 中的所有容器都在相同的 network 和 UTS 命名空间下运行,所以它们都共享相同的主机名和网络接口
这些容器也都在相同的 IPC 命名空间下运行, 因此能够通过 IPC 进行通

默认情况下, 每个容器的文件系统与其他容器完全隔离。 但我们可以使用名为 Volume 的 Kubernetes 资源来共享文件目录

容器如何共享相同的IP和端口空间

由于一个 pod 中的容器运行于相同的 Network 命名空间,因此它们共享相同的 IP 地址和端口空间

在同一 pod 中的容器运行的多个进程需要注意不能绑定到相同的端口号, 否则会导致端口冲突,但这只涉及同
-pod 中的容器

由千每个 pod 都有独立的端口空间, 对于不同 pod 中的容器来说则永远不会遇到端口冲突

平坦pod间网络

检查现有 pod 的 YAML 描述文件

kubectl get po kubia-zxzij -o yaml

pod 定义的主要部分:
首先是 YAML 中使用的 Kub etes 版本和YAML 描述的资源类型;其次是几乎在所有k8s 资源中都可找到的三大部分:
metadata 包括名称、命名空间、标签和关于该容器的其他信息;
spec 包含 pod 内容的实际说明 例如 pod 的容器、卷和其他数据
status 包含运行中的 pod 的当前信息,例如 pod所处的条件每个容器的描述和状态,以及内部 IP 和其他基本信息;

新建pod 描述:

使用 kubectl explain 来发现可能的 API 对象字段,转到 http: /kubemetes.io docs/api 上的 Kubemetes参考文档查看每个 API 对象支持哪些属性

查看应用日志
$ docker logs
$ kubectl logs kubia-manual

获取多容器 pod 的日志时指定容器名称:
-c <容器名称>选项来显式指定容器名称
kubectl logs kubia-manual -c kubia

标签

标签是可以附加到资源的任意键值对,用以选择具有该确切标签的资源(这是通过标答选择器完成的 )
只要标签的key在资源内是唯一的, 一个资源便可以拥有多个标签

创建pod时指定标签

查看标签
$ kubectl get po --show-labels

$ kubectl get po -L creation_method,env -L 指定特定标签的key

标签选择器:
$ kubectl get po -l crea七ion_me七hod=manual
$ kubectl get po -l env
$ kubectl get po -l '!env'

使用标签分类工作节点

将pod 调度到特定的节点

为node 打标签
$ kubectl label node gke-kubia-85f6-node-Orrx gpu吐rue

选择
$ kubectl ge七 nodes -1 gpu=true
将pod 调度到特定节点

注解

pod和其他对象还可以包含庄解,注解也是键值对,所以它们本质
上与标签非常相似。但与标签不同,注解并不是为了保存标识信息而 存在的,它们
不能像标签 一 样用千对对象进行分组。当我们可以通过标签选择器选择对象时,就
不存在注解选择器这样的东西。

注解 可以容纳更多的信息:

查看注解
$ kubectl get po kubia-zxzij -o yaml

添加和修改注解:
$ kubectl annotate pod kubia-manual mycompany.com/someannotation="foo bar"

命名空间对资源分组

Kubernetes命名空间简单地为对象名称提供了 个作用域,资源组织到多个命名空间,允许我 多次使用相同的资源名称(跨不同的命名空间〉
列出所有命名空间:
$ kubectl get ns

$ kubectl get po --namespace kube-system
-n

创建一个命名空间:

$ kubectl create - f custom-na espace yaml

命令行创建
$ kubectl create namespace custom-namespace

指定命名空间构建对像
$ kubectl create -f kubia-manual.yaml -n custom-namespace

停止和删除pod

按名称删除
$ kubectl delete po kubia-gpu

使用标签选择器删除 pod
$ kubectl delete po -l creation_method=manual

通过删除整个命名空间来删除 pod
$ kubectl delete ns custom-namespace ( pod 将会伴随命名空自动删除)

删除命名空间中的所有 pod ,但保留命名空间:


$ kubectl delete all --all

命令中的第一个 all 指定正在删除所有资源类型, 而 --all 选项指定将删除所有资源实例而不是按名称指定它们

第四章 副本机制和其他控制器

存活探针检查容器是否还在运行,如果探测失败, Kubemetes 将定期执行探针并重新启动容器
三种探测容器的机制:
1,HTTPGET探针对容器的 IP 地址(你指定的端口和路径)执行 HTTP GET 请求
如果探测器收到响应,并且响应状态码不代表错误(换句话说,如果HTTP
响应状态码是2xx或3xx), 则认为探测成功。如果服务器返回错误响应状态
码或者根本没有响应,那么探测就被认为是失败的,容器将被重新启动
2,TCP套接字探针尝试与容器指定端口建立TCP连接。如果连接成功建立,则
探测成功。否则,容器重新启动。
3,Exec探针在容器内执行任意命令,并检查命令的退出状态码。如果状态码是 0, 则探测成功。所有其他状态码都被认为失败

ReplicationController

是一种Kubemetes资源,可确保它的pod始终保持运行状态。如果pod因任何原因消失(例如节点从集群中消失或由于该pod已从节点中逐出),
则ReplicationController 会注意到缺少了pod并创建替代pod。

创建一个RC

使用 ReplicaSet而不是ReplicationController
ReplicaSet 的行为与ReplicationController 完全相同,但pod 选择器的表达能力更强
ReplicaSet 的选择器还允许匹配缺少某个标签的 pod, 或包含特定标签名的 pod, 不管其值如何

定义ReplicaSet

使用 DaemonSet在每个节点上运行一个pod

如果节点下线, DaemonSet不会在其他地方重新创建pod。 但是, 当将 一个新节点添加到集群中时, DaemonSet会立刻部署一个新的pod实例
集群管理员已经向所有此类节点添加了 disk ssd 的标签
$ kubectl label node min土kube disk=ssd

从节点上删除所需的标签,修改标签、
$ kubectl label node minikube disk=hdd --overwrite

介绍Job资源

它允许你运行一种 pod, 该 pod 在内部进程成功结束时, 不重启容器。一旦任务完成, pod 就被认为处千完成状态

客户端发现pod 并与之通信

pod 需要一种寻找其他 pod 的方法来使用其他 pod 提供的服务
pod 是短暂的-它们随时会启动或者关闭
Kubernetes 在 pod 启动前会给已经调度到节点上的pod 分配 IP 地址
水平仲缩意味着多个 pod 可能会提供相同的服务

服务:
Kubemetes 服务是一种为一组功能相同的 pod 提供单一不变的接入点的资源。
当服务存在时,它的 IP 地址和端口不会改变。 客户端通过 IP 地址和端口号建立连接,这些连接会被路由到提供该服务的任意一个 pod 上

创建服务

配置服务上的会话亲和性:
如果多次执行同样的命令, 每次调用执行应该在不同的pod上。 因为服务代理。通常将每个连接随机指向选中的后端 pod中的一个,即使连接来自于同一个客户端

如果多次执行同样的命令, 每次调用执行应该在不同的pod上。 因为服务代理,通常将每个连接随机指向选中的后端 pod中的一个,即使连接来自于同一个客户端

另 一方面,如果希望特定客户端产生的所有请求每次都指向同 一个 pod, 可以设置服务的 sessionAffinity 属性为ClientIP (而不是 None,None是默认值

同—个服务暴露多个端口

服务发现

Kubemetes 还为客户端提供了发现服务的 IP 和端口的方式。
通过环境变量发现服务 :
在pod 开始运行时,k8s 会初始一系列的环境变量指向现在存在的服务,
如果创建的服务早于客户端pod的创建
pod 上的进程可以根据环境变量获得服务 IP 地址和端口号

通过DNS 服务发现

第六章 将卷挂载至容器

pod 中的每个容器都有自己独立的文件系统, 因为文件系统来自容器镜像
每个新容器都是通过在构建镜像时加入的详细配置文件来启动的
容器时短暂的,容器进程崩溃后,通过存活探针启动的容器不会识别前一个容器的文件系统(已保存的数据)

持久化数据:
Kubemetes 通过定义存储卷来满足这个需求,它们不像 pod 这样的顶级资源,而是被定义为 pod 的一部分, 并和 pod 共享相同的生命周期
这意味着在 pod 启动
时创建卷, 并在删除 pod时销毁卷。 因此, 在容器重新启动期间, 卷的内容将保持不变, 在重新启动容器之后, 新容器可以识别前一个容器写入卷的所有文件。另外,如果一个 pod 包含多个容器, 那这个卷可以同时被所有的容器使用。

可用的卷类型:
emptyDir 用于存储临时数据的简单空目录。
hostPath 用于将目录从工作节点的文件系统挂载到pod中
gitRepo 通过检出Git仓库的内容来初始化的卷
nfs 挂载到pod中的NFS共享卷

emptmDir 卷:
卷从一个 目录开始,运行在 pod 内的应用程序可以写入它需要 的任何文件。因为卷的生存周期与 pod 的生存周期相关联,所以 删除 pod 时,卷的内容就会丢失。
一个 emptyDir 卷对于在同 一个pod 中运行的容器之间共享文件特别有用,也可以被单个容器用于将数据临时写入磁盘
创建pod 示例:

从一个克隆的 Git 仓库中运行 web 服务器 pod 的服务文件:仓库中保存着静态的html

在创建 pod 时,首先将卷初始化为 个空目录,然后将制定的Git 仓库克隆到其中。 如果没有将目录设置为 .( 句点),存储库将会被克隆到 kubia-website-exampl示例目录中,远不是我们想要的结果 我们预期将 repo 克隆到卷的根目录中 在设置存储库时,我们还需要指明让 Kubemetes 换到 master 分支所在的版本来创建存储卷修订变更

仓库数据改变后,容器内的数据不变,需要删除pod 后重建
gitRepo 和emptyDir 卷的内容都会在 pod 被删除时被删除

hostpath 访问工作节点文件系统的文件,第一种持久性存储

某些系统级别的 pod( 切记, 这些通常由 DaemonSet 管理)确实需要读取节点的文件或使用节点文件系统来访问节点设备
hostPath 卷指向节点文件系统上的特定文件或目录
在同一个节点上运行并在其 hostPath 卷中使用相同路径的 pod 可以看到相同的文件
卷的内容存储在特定节点的文件系统中,当数据库 pod被重新安排在另 一个节点时, 会找不到数据

挂载nfs

持久卷和持久卷声明

ConfigMap 和Secret

配置容器化程序的方法:
向容器传递命令行参数
为每个容器设置自定义环境变量
通过特殊类型的卷将配置文件挂载到容器中

向容器内传递命令行参数

在Docker中定义命令与参数:

容器中运行的完整指令由两部分组成:命令与参数

ENTRYPOINT与CMD
Dockerfile中的两种指令分别定义命令与参数这两个部分
1,ENTRYPOINT定义容器启动时被调用的可执行程序
2,CMD指定传递给ENTRYPOINT的参数
尽管可以直接使用CMD指令指定镜像运行时想要执行的命令, 正确的做法依旧是借助ENTRYPOINT指令, 仅仅用CMD指定所需的默认参数。 这样, 镜像可以直接运行, 无须添加任何参数
$ docker run
或添加一些参数,覆盖Dockerile中任何由CMD指定的默认参数值
$ docker run

了解shell与exec形式的区别:

上述两条指令均支持以下两种形式:
shell形式一如 ENTRYPOINT node app.js。
exec形式一如ENTRYPOINT ["node", "app. j s"]。

两者的区别在于指定的命令是否是在shell中被调用:
如果使用exec形式的ENTRYPOINT指令,从容器的进程列表可看,直接运行node进程, 而并非在shell中执行

如果采用shell形式(ENTRYPO工NT node app.js),进程列表显示:

可以看出:主进程(PID 1)是shell进程而非node进程,node进程(PID 7)于shell中启动,

shell进程往往是多余的, 因此通常可以直接采用exec形式的ENTRYPOINT指令。

在k8s中覆盖命令和参数

在 Kubemetes 中定义容器时, 镜像的 ENTRYPOINT 和 CMD 均可以被覆盖, 仅需在容器定义中设置属性command 和 args的值


为容器设置环境变量

与容器的命令和参数设置相同,环境变量列表无法在pod创建后被修改。
容器中的脚本已设定使用变量,在k8s容器定义中使用环境变量

环境变量被设置在pod的容器定义中,并非是pod级别
注意:不要忘记在每个容器中,Kubemetes会自动暴露相同命名空间下每个service对应的环境变量。这些环境变量基本上可以被看作自动注入的配置

在环境变量中引用其他环境变量

pod 定义硬编码 意味着需要有效区分生产环境与开发过程中的 pod 定义
为了能在 多环境下复用 pod 定义, 要将配置从 pod 定义描述中解藕出来

利用 ConfigMap解耦相配置

Kubemetes 允许将配置选项分离到单独的资源对象ConfigMap 中, 本质上就是个键值对映射,值可以是短字面量,也可以是完整的配置文件

创建ConfigMap
使用指令 kubectl 创建 ConfigMap
$ kubectl create configmap fortune-config --from-literal=sleep-interval=25 创建一个简单的字面变量

注意 ConfigMap 中的键名必须是一个合法的 DNS 域,仅包含数字字母、破折号、下画线以及圆点,首位的圆点符号是可选的
效果:

创建多个条目;通过添加多个 --from-literal 参数可创建包含多条目的 ConfigMap

kubectl create configmap myconfigmap --from-literal=foo=bar --from-literal=bar=baz --from-literal=one=two
查看ConfigMap 的YAML定义
kubectl get configmap fortune-config - o yaml

  • 从文件内容创建ConfigMap 条目
    kubectl create configmap 命令支持从磁盘上读取文件,并将文件内容单独存储为ConfigMap中的条目
    $ kubectl create configmap my-config --from-file=config-file.conf
    运行命令会在当前目录下查找config-file conf 文件,并将文件内容存储在 ConfigMap中以config-file.conf为键名的条目下
    当然也可以手动指定键名:
    kubectl create configmap my-config -from-file=customkey=config-file.conf

这条命令会将文件内容存在键名为 customkey 目下 与使用字面量时相同,多次使用 --from -ile 参数可增加多个文件条目

  • 从文件夹创建 ConfigMap
    引入某一文件夹中的所有文件
    $ kubectl create configmap my-config --from-file=/path/ to/ dir
    kubectl 会为文件夹中的每个文件单独创建条目,仅限于那些文件名可作为合法 ConfigMap键名的文件

合并不同选项:
可混合使用以上提到的所有选项

给容器传递 ConfigMap 条目作为环境变量

1,设置环境变量
通过配置文件注入环境变量的pod:

2,一次性传递 ConfigMap 的所有条目作为环境变量

3,传递 ConfigMap 条目作为命令行参数
4,使用 configMap 卷将条目暴露为文件

从文件夹创建
$ kubectl create configmap fortune-config --from-file=configmap-files

ConfigMap 包含两个条目,条目的键名与文件名相同
使用:
在卷内使用ConfigMap 的条目
创建包含ConfigMap条目内容的卷只需要创建一 个引用ConfigMap名称的卷并挂载到容器中

说明:使用configmap 初始化一个卷,卷目录下为configmap 的条目,然后使用卷挂载将卷挂载到pod 的指定目录下。

检查被挂载的configMap卷的内容
$ kubectl exec fortune-configmap-volume -c web-server ls /etc/nginx/conf.d
ConfigMap的两个条目均作为文件置于这一文件夹下

  • 卷内暴露指定的ConfigMap条目

挂载某一文件夹会隐藏该文件夹中已存在的文件
将卷挂载至某个文件夹,意味着容器镜像中/etc/nginx/conf.d文件夹下原本存在的任何文件都会被隐藏

ConfigMap独立条目作为文件被挂载且不隐藏文件夹中的其他文件
volumeMount额外的subPath字段可以被用作挂载卷中的某个独立文件或者是文件夹,无须挂载完整卷
通过属性subPath可以将该文件挂载的同时又不影响文件夹中的其他文件。

为configMap卷中的文件设置权限
configMap卷中所有文件的权限默认被设置为644 (-rw-r-r--)。

通过卷规格定义中的defaultMode属性改变默认权限

更新应用配置且不重启应用程序

将ConfigMap暴露为卷可以达到配置热更新的效果, 无须重新创建pod或者重启容器
ConfigMap被更新之后, 卷中引用它的所有文件也会相应更新, 进程发现文件被改变之后进行重载

注意:更新ConfigMap之后对应文件的更新耗时会出人意杜地长(往往需要数分钟)

kubectl edit configmap fortune-config
修改configmap 后pod 挂载的卷会自动更新。但是pod 内的进程并不会自动读取配置文件重启

挂载至已存在文件夹的文件不会被更新: 即挂载到容器的configmap 不是完整的卷,只是一个configmap 中的一个条目
ConfigMap更新之后对应的文件不会被更新。

了解更新 ConfigMap 的影响
ConfigMap更新之后创建的pod会使用新配置, 而之前的pod依旧使用旧配置

使用 Secret给容器传递敏感数据

提供了一种称为 Secret 的单独资源对象。 Secret 结构与 ConfigMap类似, 均是键/值对的映射。 Secret 的使用方法也与
ConfigMap 相同, 可以:
将 Secret 条目作为环境变量传递给容器
将 Secret 条目暴露为卷中的文件

Kubemetes 通过仅仅将 Secret 分发到需要访问 Secret 的 pod所在的机器节点来保障其安全性。 另外, Secret 只会存储在节点的内存中, 永不写入物理存储,

对于主节点本身(尤其是 etcd), Secret 通常以非加密形式存储, 这就需要保障主节点的安全从而确保存储在 Secret 中的敏感数据的安全性

1,默认令牌 Secret 介绍
一种默认被挂载至所有容器的 Secret,
default-token Secret默认会被挂载至每个容器。 可以通过设置pod定义中的automountServiceAccountToken字段为false, 或者设置pod使用
的服务账户中的相同字段为false来关闭这种默认行为

kubectl create secret generic fortune-https --from-file=h七tps.key --from-file=h七七ps.cer七 --from-file=foo

kubectl get configmap fortune-config -o yaml secret 的条目是由base64编码的

示例:

通过环境变量暴露Secret 条目

拉取私有仓库的鉴权,使用secret

在pod 中使用

从应用访问元数据及其他资源

Deployment :声明式的升级应用

更新pod内镜像的方法:更新pod
1,直接删除所有现有的 pod, 然后创建新的 pod
2,也可以先创建新的 pod, 并等待它们成功运行之后, 再删除旧的 pod。 可以先创建所有新的 pod, 然后一次性删除所有旧的 pod, 或者按顺序创建新的pod, 然后逐渐删除旧的 pod

原文地址:https://www.cnblogs.com/g2thend/p/11509403.html