k8s 的基本概念
Kubernetes是一个可以移植、可扩展的开源平台,使用 声明式的配置 并依据配置信息自动地执行容器化应用程序的管理。在所有的容器编排工具中(类似的还有 docker swarm / mesos等),Kubernetes的生态系统更大、增长更快,有更多的支持、服务和工具可供用户选择。
Kubernetes的名字起源于希腊语,含义是 舵手
、领航员
、向导
。Google于2014年将Brog系统开源为Kubernetes。Kubernetes构建在Google Brog 十五年运行大规模分布式系统的经验 (opens new window)基础之上,并结合了开源社区最好的想法和实践。
Master组件
Kube-apiserver: 集群的控制中心,各个模块直接的通信和信息传输都要经过我们kube-apiserver,它同时负责集群的管理,资源的分配,整个集群的安全机制入口。
controller-manager: 集群的状态管理器,保证pod或其他资源都达到期望值。也就是和Kube-apiserver进行通信,在需要的时候创建更新或者删除资源。
scheduler调度中心,它会根据指定条件去做筛选,选择一个或者一批最佳的节点然后部署我们的pod。
Etcd 键值数据库,保存一些集群的信息,一般生成环境建议是三个节点(奇数台)
Node组件
Kubelet:负责监听节点上pod的状态,同时负责上报节点和节点上面pod的状态,负责与master节点通信,并且管理pod。
Kube-proxy:负责pod之间通信和负载均衡,将制定的流量分发到后端正确的机器上。查看kube-proxy工作模式
netstat -lntp | grep kube-proxy
curl 127.0.0.1:10249/proxyMode
iptables:监听Master节点增加和删除service以及endpoint的消息,对于每一个service它会用iptables规则,将servcie的cluster代理到pod上面
ipvs:监听Master节点增加和删除service以及endpoint的消息,调用ipvs规则映射到pod上面。
calico:网络插件,给每个pod生成唯一的ip地址,并把每个节点当做一个路由。
coredns:用于service解析,可以让pod把service名称解析成ip地址,然后通过service的ip地址链接到对应的应用上。
docker:容器引擎,负责容器管理。
pod
k8s最小管理单元、
kubectl get pod
一个pod它是一组或者一个或者多个容器组成。每个pod还包含了一个pause容器,pause容器就是pod的父容器,主要负责僵尸进程的回收管理,通过pause容器可以使同一个pod里面的多个容器实现共享存储网络PID ipc等
管理pod:pod容器可以进行替换,不一定是哪一种。
定义一个pod
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
# namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace
labels: # 可选,标签选择器,一般用于过滤和区分Pod
app: nginx
role: frontend # 可以写多个
annotations: # 可选,注释列表,可以写多个
app: nginx
spec: # 必选,用于定义容器的详细信息
# initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作
# - command:
# - sh
# - -c
# - echo "I am InitContainer for init some configuration"
# image: busybox
# imagePullPolicy: IfNotPresent
# name: init-container
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: nginx:1.8 # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去
command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd
- nginx
- -g
- "daemon off;"
workingDir: /usr/share/nginx/html # 可选,容器的工作目录
# volumeMounts: # 可选,存储卷配置,可以配置多个
# - name: webroot # 存储卷名称
# mountPath: /usr/share/nginx/html # 挂载目录
# readOnly: true # 只读
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置列表
- name: TZ # 变量名
value: Asia/Shanghai # 变量的值
- name: LANG
value: en_US.utf8
# resources: # 可选,资源限制和资源请求限制
# limits: # 最大限制设置
# cpu: 1000m
# memory: 1024Mi
# requests: # 启动所需的资源
# cpu: 100m
# memory: 512Mi
# startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: /api/successStart # 检查路径
# port: 80
# readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: / # 检查路径
# port: 80 # 监控端口
# livenessProbe: # 可选,健康检查
#exec: # 执行容器命令检测方式
#command:
#- cat
#- /health
#httpGet: # httpGet检测方式
# path: /_health # 检查路径
# port: 8080
# httpHeaders: # 检查的请求头
# - name: end-user
# value: Jason
# tcpSocket: # 端口检测方式
# port: 80
# initialDelaySeconds: 60 # 初始化时间
# timeoutSeconds: 2 # 超时时间
# periodSeconds: 5 # 检测间隔
# successThreshold: 1 # 检查成功为2次表示就绪
# failureThreshold: 2 # 检测失败1次表示未就绪
# lifecycle:
# postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket
# exec:
# command:
# - sh
# - -c
# - 'mkdir /data/ '
# preStop:
# httpGet:
# path: /
# port: 80
# exec:
# command:
# - sh
# - -c
# - sleep 9
restartPolicy: Always # 可选,默认为Always,容器故障或者没有启动成功,那就自动该容器,Onfailure: 容器以不为0的状态终止,自动重启该容器, Never:无论何种状态,都不会重启
#nodeSelector: # 可选,指定Node节点
# region: subnet7
# imagePullSecrets: # 可选,拉取镜像使用的secret,可以配置多个
# - name: default-dockercfg-86258
# hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口
# volumes: # 共享存储卷列表
# - name: webroot # 名称,与上述对应
# emptyDir: {} # 挂载目录
# #hostPath: # 挂载本机目录
# # path: /etc/hosts
pod工作原理
我们很少在Kubernetes中直接创建单个Pod。这是因为Pods被设计成相对短暂的、一次性的实体。 当一个POD被创建(直接创建,或间接由控制器创建)时,它被安排在集群中的节点上运行。 在进程终止、pod对象被删除、pod由于缺乏资源而被驱逐或节点失败之前,POD仍然位于该节点上。
**注意:**不要将重新启动Pod中的容器与重新启动Pod混淆。POD不是一个进程,而是一个运行容器的环境。Pod一直存在直到被删除为止。
pod本身无法自我修复。如果将Pod调度到发生故障的节点,或者调度操作本身失败,则将Pod删除;同样,由于缺乏资源或Node维护,Pod也被删除。Kubernetes使用称为控制器的更高级别的抽象来处理管理相对一次性的Pod实例的工作。因此,虽然可以直接使用Pod,但在Kubernetes中使用控制器来管理Pod更为常见。
pod和控制器关系
你可以使控制器创建和管理多个pod。控制器在pod失败的情况下可以处理副本、更新以及自动修复。例如,如果某个节点发生故障,则控制器会注意到该节点上的Pod已停止工作,并创建了一个替换Pod。调度程序将替换的Pod放置到健康的节点上。可以使用deployment、statefulset、daemonset等控制器管理pod。
pod模板介绍
控制器(如deployment、daemonset、statefulset等)是通过创建pod模板来创建和管理pod的,PodTemplate是用于创建pod的规范,并且包含在deployment、job和daemonset中。每个控制器使用自己内部的Pod模板来创建实际的Pod。PodTemplate是运行应用程序所需的任何控制器的一部分。下面的示例是一个简单的Job的清单,包含一个podtemplate,这个是用来生成pod的模板。该Pod中的容器会打印一条消息,然后暂停。
vi job-template.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# This is the pod template
spec:
containers:
- name: hello
image: busybox
command: ['sh', '-c', 'echo "Hello, Kuboard!" && sleep 3600']
restartPolicy: OnFailure
# The pod template ends here
修改pod template或切换到新的pod tmplate对已经存在的pod没有影响。 POD不直接接收模板更新,而是创建一个新的POD来匹配修改后的POD模板。例如,控制器可确保正在运行的Pod与当前Pod模板匹配。如果模板已更新,则控制器必须删除现有的Pod并根据更新的模板创建新的Pod。每个控制器都实现自己的规则来处理Pod模板的更改。在节点上,kubelet不直接观察或管理有关Pod模板和更新的任何详细信息。
pod 相关的文档查看
和pod相关的api对象
kubectl explain pods
上面命令可以看到和pod相关的api对象有哪些,也就是通过资源清单yaml部署一个pod时需要哪些字段
apiVersion
apiVersion定义了此对象表示的版本化模式。服务器应将已识别的模式转换为最新的内部值,并可能拒绝无法识别的值。更多信息参考:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
查看k8s集群支持的apiVersion有哪些,可以使用下面的命令:
kubectl api-versions
显示如下支持apiVersion信息:
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
batch/v1
batch/v1beta1
certificates.k8s.io/v1beta1
coordination.k8s.io/v1
coordination.k8s.io/v1beta1
crd.projectcalico.org/v1
discovery.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
metrics.k8s.io/v1beta1
networking.k8s.io/v1
networking.k8s.io/v1beta1
node.k8s.io/v1beta1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
scheduling.k8s.io/v1
scheduling.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1
kind
Kind是表示此对象表示的REST资源的字符串值。服务器可以从客户端提交请求的端点推断出这一点,说白了就是表示我们要创建什么资源,如deployment、statefulset、pod、service、ingress
查看更详细信息可参考:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata
标准对象的元数据。更多信息:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec
指定容器的所需行为。更多信息:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
status
最近观察到的pod的状态。此数据可能不是最新的。Status不需要在pod或者其他资源中定义,这个默认是存在的,更多信息:https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
怎么命令行工具创建pod?
1.通过定义资源清单yaml文件(就是以yaml结尾的文件)创建pod,在k8s的master节点操作
查看定义资源清单需要哪些字段
kubectl explain pods
kubectl explain pods.apiVersion
kubectl explain pods.kind
kubectl explain pods.metadata
kubectl explain pods.spec
cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: web
namespace: default
labels:
web: nginx
spec:
containers:
- name: nginxdemo
image: nginx:1.8
imagePullPolicy: IfNotPresent
#通过kubectl apply创建一个pod
kubectl apply -f pod.yaml
#查看pod创建的情况
kubectl get pods
显示如下:
NAME READY STATUS RESTARTS AGE
web 0/1 ContainerCreating 0 37s
#查看pod的详细信息
kubectl describe pods web
# pod.yaml定义的所有资源都删除掉
kubectl delete -f pod.yaml yaml
#查看pod调度到哪个节点
kubectl get pods -o wide
显示如下:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web 1/1 Running 0 5m30s 10.244.1.21 node1 <none> <none>
#查看pod日志
kubectl logs web
#查看pod里指定容器的日志
kubectl logs -c nginxdemo web
#进入到刚才创建的pod,刚才创建的pod名字是web
kubectl exec -it web -- /bin/bash
#假如pod里有多个容器,进入到pod里的指定容器,按如下命令:
kubectl exec -it web -c nginxdemo -- /bin/bash
我们上面创建的pod是一个自主式pod,也就是通过pod创建一个应用程序,如果pod出现故障停掉,那么我们通过pod部署的应用也就会停掉,不安全,所以还有一种pod,
还有一种控制器管理的pod,通过控制器创建pod,可以对pod的生命周期做管理,如定义pod的副本数,如果有一个pod意外停掉,那么会自动起来一个pod替代之前的pod,之后会讲解pod的控制器
kubectl get pods
可查看到刚才创建的pod
标签
给node添加一个label标签
kubectl label node k8s-node1 "node=node1"
查看label标签
kubectl get node -l "node=node1"
- 删除label标签,只需要在命令行最后指定label的key名,并加一个减号就可以了。
kubectl label node k8s-node1 role-
- 将节点调度到指定Node
- 首先给对应需要调度的node打上标签,然后创建资源清单时添加上nodeSelector属性对应即可
kubectl label nodes k8s-node1 role=k8s-Node
[root@master NetworkPolicy]# cat pod-demo-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod2
labels:
app: nginx
spec:
containers:
- name: app-2
image: ikubernetes/myapp:v1
nodeSelector:
node: kube-Node
重启策略
#查看重启策略restartPolicy怎么定义的:
kubectl explain pods.spec.restartPolicy
Always:只要容器挂了就重启
OnFailure:只有容器状态为错误的时候才重启
Never:从不重启容器
默认重启策略就是Always
名称空间-namespace
一、什么是命名空间
Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。 这些虚拟集群被称为命名空间。
二、何时使用多个命名空间
使用命名空间 命名空间和 DNS 并非所有对象都在命名空间中 接下来 何时使用多个命名空间
命名空间适用于存在很多跨多个团队或项目的用户的场景。对于只有几到几十个用户的集群,根本不需要创建或考虑命名空间。当需要名称空间提供的功能时,请开始使用它们。命名空间为名称提供了一个范围。资源的名称需要在命名空间内是唯一的,但不能跨命名空间。命名空间不能相互嵌套,每个 Kubernetes
资源只能在一个命名空间中。命名空间是在多个用户之间划分集群资源的一种方法(通过资源配额)。
在 Kubernetes 未来版本中,相同命名空间中的对象默认将具有相同的访问控制策略。
不需要使用多个命名空间来分隔轻微不同的资源,例如同一软件的不同版本:使用 labels 来区分同一命名空间中的不同资源。
使用命名空间 命名空间的创建和删除已在命名空间的管理指南文档中进行了描述。
三、查看命名空间
您可以使用以下命令列出集群中现存的命名空间:
[root@k8s1 ~]# kubectl get namespace
NAME STATUS AGE
default Active 2d1h
kube-node-lease Active 2d1h
kube-public Active 2d1h
kube-system Active 2d1h
123456
也可以使用 ns 代替,效果与namespace 一样
kubectl get ns
Kubernetes 会创建三个初始命名空间:
- default 没有指明使用其它命名空间的对象所使用的默认命名空间
- kube-system Kubernetes 系统创建对象所使用的命名空间
- kube-public 这个命名空间是自动创建的,所有用户(包括未经过身份验证的用户)都可以读取它。这个命名空间主要用于集群使用,以防某些资源在整个集群中应该是可见和可读的。这个命名空间的公共方面只是一种约定,而不是要求。
3.1 创建命名空间
[root@k8s1 ~]# kubectl create namespace orange
namespace/orange created
查看命名空间
[root@k8s1 ~]# kubectl get namespace
NAME STATUS AGE
default Active 2d1h
kube-node-lease Active 2d1h
kube-public Active 2d1h
kube-system Active 2d1h
orange Active 5s
1234567891011
3.2当然也可以使用yaml来创建命名空间
[root@k8s1 namespace]# cat my-namespace.yaml
kind: Namespace #类型为Namespace
apiVersion: v1 #类型为Namespace
metadata:
name: orange-test #命名空间名称
labels:
name: orange-test-v1
创建命名空间
[root@k8s1 namespace]# kubectl create -f my-namespace.yaml
namespace/orange-test created
查看命名空间
[root@k8s1 namespace]# kubectl get namespace
NAME STATUS AGE
default Active 2d1h
kube-node-lease Active 2d1h
kube-public Active 2d1h
kube-system Active 2d1h
orange Active 9m44s
orange-test Active 25s
3.3 pod使用命名空间
[root@k8s1 namespace]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
llxxyy/centos-pure 7.6 c21f6df29f79 About an hour ago 1.04GB
123
[root@k8s1 namespace]# cat my-pod-namespace.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod-namespace ##pod名称
namespace: orange ##命名空间名称
labels:
app: bash
tir: backend
spec:
containers:
- name: bash-container
image: llxxyy/centos-pure:7.6 ##镜像名称:tag
command: ['sh','-c','echo hello myfirstpod && sleep 3600']
[root@k8s1 namespace]# kubectl create -f my-pod-namespace.yaml
pod/my-pod-namespace created
[root@k8s1 namespace]# kubectl get pods -n=orange
NAME READY STATUS RESTARTS AGE
my-pod-namespace 1/1 Running 0 5s
3.4 删除名称空间
语法
kubectl delete namespaces <insert-some-namespace-name>
12
[root@k8s1 namespace]# kubectl delete namespaces orange
namespace "orange" deleted
标签是什么
标签是k8s特色的管理方式,便于分类管理资源对象。
一个标签可以对应多个资源,一个资源也可以有多个标签,它们是多对多的关系。
一个资源拥有多个标签,可以实现不同维度的管理。
可以使用标签选择器来指定能使用哪些标签。
1、标签组成
key=value
- key:只能使用 字母 数字 _ - . (只能以字母数字开头,不能超过63给字符)
- value: 可以为空 只能使用 字母 数字开头
2**、定义标签**
kubectl get pods --show-labels #查看pod所有标签信息
kubectl get pods -l app #过滤包含app的标签
kubectl get pods -L app #过滤包含app的标签及显示值
kubectl label pods pod-demo release=canary #给pod-demo增加标签
kubectl label pods pod-demo release=stable --overwrite #修改标签
二、标签选择器
给资源打上标签后,可以使用标签选择器过滤指定的标签
标签选择器目前有两个:基于等值关系和基于集合关系
- 等值关系操作符:=, == , !=
#使用格式
kubectl get pods -l run=myapp
kubectl get pods -l run=myapp --show-labels
kubectl get pods -l run!=client --show-labels
- 集合关系的操作符:in,notin,exists
#使用格式
kubectl get pods -l "run in (client,myapp,alpha)" --show-labels #三个值有一个匹配上都可以
kubectl get pods -l "run notin (client,myapp,alpha)" --show-labels
1、匹配符合条件的标签,部署pod
a、给node02节点打标签,如果多个主机都有ssd标签,会随机匹配某一个
kubectl label nodes node02 disktype=ssd #给node02打上ssd标签
kubectl get nodes --show-labels
b、修改yaml文件,增加标签选择器
[root@master manifests]# cat pod-with-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-nodeselector
labels:
env: testing
spec:
containers:
- name: myapp
image: nginx:1.8
nodeSelector:
disktype: ssd
c、创建pod,验证
kubectl create -f pod-with-nodeselector.yaml
kubectl get nodes -o wide
2、通过主机名,部署pod到指定的主机
方式一:
[root@master manifests]# cat pod-with-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-nodeselector
labels:
env: testing
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
nodeSelector:
kubernetes.io/hostname: node01.linux.com
方式二:使用sepc.nodeName
[root@master manifests]# cat pod-with-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-with-nodeselector
labels:
env: testing
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
nodeName: node01
基于pod的标签
(2)查看所有pod资源对象的标签
kubectl get pods --show-labels
(3)查看带有指定标签的pod
kubectl get pods -L web1
显示所有资源对象下web1这个标签的标签值
(4)kubectl get pods -l web1 --show-labels
查看拥有web1这个标签的资源对象,并且把标签显示出来
(5)想修改资源的标签,比方说想给web加上个release标签
给资源对象打标签要使用label命令,指定给某个类型下的某个资源打标签,资源中的key/value可以是多个,因此在web(pod名字)这个资源下再打个标签release,用如下命令
kubectl label pods web release=new
查看标签是否打成功:
kubectl get pods --show-labels
显示如下,显示如下,说明标签达成功了;
NAME READY STATUS RESTARTS AGE LABELS
web 1/1 Running 1 21