Kubernetes Pod
一、Pod 介绍
每个Pod都有一个特殊的被称为“根容器”
的Pause
容器。Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用户业务容器
为什么Kubernetes会设计出一个全新的Pod概念,并且有这样特殊的结构?
原因一:Pause容器作为Pod根容器,以它的状态代表整个容器组的状态 原因二: Pod里的多个业务容器共享Pause容器的IP,共享Pause容器挂接的Volume
Kubernetes为每个Pod分配唯一的IP的地址,称之为Pod IP
,一个Pod里的多个容器共享
Pod IP。Kubernetes要求底层网络支持集群内任意两个Pod之间的TCP/IP的直接通讯,采用虚拟二层网络技术来实现,一个Pod里的容器与另外主机上的Pod容器能够直接通信。
静态Pod & 普通Pod
普通的Pod:
普通Pode一旦被创建,就会被放入到etcd
中存储,随后会被Kubernetes Master调度到某个具体的Node上并进行绑定(Binding)
,随后该Pod 被对应的Node上的kubelet进程实例化成一组相关的docker容器运行起来。
当Pod里的某个容器停止时,Kubernetes会自动检测到这个问题并且重新启动这个Pod (重启Pod里的所有容器),如果Pod所在的Node宕机,则会将这个Node上所偶的Pod从新调度到其他节点上。
静态Pod (STatic Pod)
静态Pod不存放在Kubernetes的etcd存储里,而是存放在某个具体的Node上的文件中,并且只在此Node上启动运行。
静态Pod是由kubelet进行管理的仅存在于特定Node上的Pod。他们不能通过API Server进行管理,无法与ReplicationController(RC)、Deployment、或者DaemonSet进行关联,并且kubelet也无法对它们进行健康检查。静态Pod总是由kubelet进行创建的,并且总是在kubelet所在的Node上运行的
创建静态Pod有两种方式:配置文件方式和HTTP方式
1.配置文件方式
首先,需要设置kubelet的启动参数"config",指定kubelet需要监控的配置文件所在的目录,kubelet会定期扫描该目录,并根据该目录中的*.yaml
或*.json
文件进行创建操作
部署静态Pod
1.选择一个节点来运行静态pod
[root@abcdocker ~] $ ssh master
2.选择一个目录,例如/etc/kubelet.d,把web服务器的pod定义文件放在这个目录下,例如/etc/kubelet.d/static-web.yaml:
[root@my-node1 ~] $ mkdir /etc/kubelet.d/
[root@my-node1 ~] $ cat <<EOF >/etc/kubelet.d/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
3.配置节点上的kubelet使用这个目录,kubelet启动时增加--pod-manifest-path=/etc/kubelet.d/参数。如果是Fedora系统,在Kubelet配置文件/etc/kubernetes/kubelet中添加下面这行:
...
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=/etc/kubelet.d/"
...
4.重启kubelet
[root@abcdocker ~] systemctl restart kubelet
提示:由于Pod无法通过API Server直接进行管理,所以Master节点尝试删除这个Pod,将会使其状态变成Pending
状态,且不会被删除
2.使用HTTP方式
这里不再介绍了,有兴趣的可以去官方文档下面看一下 https://kubernetes.io/cn/docs/tasks/administer-cluster/static-pod/
Endpoint
Pod的IP加上这里的容器端口(container Port)
,就组成了一个全新的概念---Endpoint
它代表着此Pod里的一个服务进程的对外通讯地址。一个Pod也存在着多个Endpoint的情况,比如我们把Tomcat定义为一个Pod时,可以对外暴露端口与服务端口这两个Endpoint
Event
Event是一个事件的记录,记录事件的最早生成时间、最后重现时间、重复次数、发起者、类型,以及导致此事件的原因等众多信息。Event通常会关联到某个具体的资源上,是排查故障的重要参考,Node描述信息包含了Event,而Pod同样有Event记录。
当我们发现某个Pod迟迟无法创建时,我们就可以用kubectl describe pod [Pod名称]
来查看,定位问题
演示:
$ 使用kubectl get pod 可以查到当前Pod数
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-5c6b9976cc-2qbkr 0/1 ContainerCreating 0 14s
nginx-deployment-5c6b9976cc-bqtvp 0/1 ContainerCreating 0 14s
nginx-deployment-5c6b9976cc-ttdrz 0/1 ContainerCreating 0 14s
$ 使用kubetctl describe pod [Pod名称]可以看到Pod详细信息
[root@master ~]# kubectl describe pod nginx-deployment-5c6b9976cc-2qbkr
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 35s default-scheduler Successfully assigned default/nginx-deployment-5c6b9976cc-2qbkr to master
Warning FailedCreatePodSandBox 6s (x2 over 28s) kubelet, master Failed create pod sandbox: rpc error: code = Unknown desc = failed pulling image "gcr.io/google_containers/pause-amd64:3.0": Error response from daemon: Get https://gcr.io/v1/_ping: dial tcp 74.125.203.82:443: getsockopt: connection timed out
一个完整的Pod,正常创建没有错误如下
$ 显示一个Pod完整信息
[root@master ~]# kubectl describe pod tomcat-6755d5587c-nfjst
Name: tomcat-6755d5587c-nfjst
Namespace: default
Node: master/192.168.60.24
Start Time: Wed, 18 Jul 2018 16:29:37 +0800
Labels: app=abcdocker
pod-template-hash=2311811437
Annotations: <none>
Status: Running
IP: 172.17.0.2
Controlled By: ReplicaSet/tomcat-6755d5587c
Containers:
tomcat:
Container ID: docker://415acd35b6d4ed3effd26e2d9a958a56e83619243b0216690e0573a6c079bf1f
Image: daocloud.io/library/tomcat
Image ID: docker-pullable://daocloud.io/library/tomcat@sha256:1c39cc2e882b4169199888
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Wed, 18 Jul 2018 16:33:18 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-cbkfr (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-cbkfr:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-cbkfr
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: <none>
Events: <none>
二、Pod基本用法
Pod的基本用法为:Pod 可以创建一个或多个容器组合而成
创建一个名为nginx-deployment的Pod只由一个容器组成
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 5
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx ##容器名称
image: daocloud.io/library/nginx:1.13.0-alpine #镜像地址
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
另一种场景,当nginx容器和tomcat容器应用为紧耦合的关系,应该组合成一个整体对外提供服务时,应将这两个容器打包为一个Pod
配置nginx和tomcat yaml文件如下下
[root@master test]# cat abcdocker.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: abcdocker-pod
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- name: abcdocker-nginx-docker
image: daocloud.io/library/nginx:1.13.0-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
- name: abcdocker-tomcat-docker
image: daocloud.io/library/tomcat:8.5.21-jre8-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
[root@master test]# kubectl create -f abcdocker.yaml
##参数解释
我们可以看到READY信息为2/2,表示Pod中的两个容器都成功运行了 (状态Running)
查看Pod的详细信息,我们可以看到两个容器的定义及创建的过程 Event信息事件
[root@master ~]# kubectl describe pod abcdocker-pod-dc6b86f8d-7tjwp
Name: abcdocker-pod-dc6b86f8d-7tjwp
Namespace: default
Node: master/192.168.60.24
Start Time: Fri, 31 Aug 2018 11:06:02 +0800
Labels: app=test
pod-template-hash=872642948
Annotations: <none>
Status: Running
IP: 172.16.219.106
Controlled By: ReplicaSet/abcdocker-pod-dc6b86f8d
Containers:
abcdocker-nginx-docker: ## 容器名称
Container ID: docker://63d038a53c613e0dfdb62df957035f0ab54cc5428461c33f9cbcee0118815619
Image: daocloud.io/library/nginx:1.13.0-alpine ##容器镜像
Image ID: docker-pullable://daocloud.io/library/nginx@sha256:5c36f962c506c379bd63884976489c9c5e700c1496a6e8ea13dc404b1d258f76
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Fri, 31 Aug 2018 11:06:17 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-c6m5g (ro)
abcdocker-tomcat-docker:
Container ID: docker://42e0e6ee79860c5dac6a9103c549bd47422e8044f2c57046f6ad4dcca346f743
Image: daocloud.io/library/tomcat:8.5.21-jre8-alpine
Image ID: docker-pullable://daocloud.io/library/tomcat@sha256:96a11198cf980995e61d906ba65b1c86934ffc4c7e9381157d2aebd8981a4480
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Fri, 31 Aug 2018 11:07:20 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-c6m5g (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-c6m5g:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-c6m5g
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: <none>
Events: <none>
三、Pod的配置管理 ConfigMap
应用部署的一个最佳实践是讲应用所需的配置信息与程序进行分离,这样可以使得应用程序被更好地复用,通过不同的配置也能实现灵活的功能。将应用打包为容器镜像后,可以通过环境变量或者外挂文件的方式在创建容器时进行配置注入,但在大规模容器集群中,对多个容器进行不同的配置将变得非常复杂。从kubernetes1.2开始提供了一套同意的应用配置管理方案----ConfigMap(资源对象)
ConfigMap概述
ConfigMap供容器使用的典型用法如下
- 生成为容器内的环境变量
- 设置容器的启动命令的启动参数 (需要设置为环境变量)
- 以Volume的形式挂载为容器内部的文件或目录
ConfigMap以一个或多个key:value的形式保存在Kubernetes系统中供应用使用,既可以用于表示一个变量的值(例如apploglevel=info),也可以用于表示一个完整配置文件的内容(server.xml=<?xml..>..)
可以通过yaml配置文件或者直接使用kubectl create configmap
来创建ConfigMap
创建ConfigMap
创建ConfigMap的方式有4种:
- 通过直接在命令行中指定configmap参数创建,即--from-literal
- 通过指定文件创建,即将一个配置文件创建为一个ConfigMap--from-file=<文件>
- 通过指定目录创建,即将一个目录下的所有配置文件创建为一个ConfigMap,--from-file=<目录>
- 事先写好标准的configmap的yaml文件,然后kubectl create -f 创建
1、使用yaml文件创建ConfigMap
==演示: 通过定义yaml配置文件方式创建ConfigMap==
cat > configmap-test.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: test-configmap
data:
key1: abcdocker1
keydir: /var/data
EOF
# name: configmap名称
data.key1: key1 对应的值
data.keydir: keydir对应的挂载目录
创建并查看Configmap
[root@master configmap]# kubectl create -f configmap-test.yaml
configmap/test-configmap created
[root@master configmap]# kubectl get configmaps
NAME DATA AGE
test-configmap 2 5s
# 这里我们可以看到创建了2个data的数据,就是我们上面定义的
查看创建好的configMap
[root@master configmap]# kubectl describe configmaps test-configmap
Name: test-configmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
key1:
----
abcdocker1
keydir:
----
/var/data
Events: <none>
# Data下面是对应的我们上面定义的key和挂载的目录
2、使用--from-file参数创建ConfigMap
==演示: 通过--from-file参数从文件中进行创建,可以指定key的名称,也可以在一个命令行中创建多个key的ConfigMap==
语法格式
kubectl create configmap Name --from-file=[key=]source --from-file=[key=]source
例:当前目录下含有配置文件server.xml,可以创建一个包含该文件内容的ConfigMap
kubectl create configmap test-server.xml --from-file=server.xml
例:当前configfiles下有2个配置文件,创建一个configmap包含2个文件内容
kubectl create configmap two-conf --from-file=configfiles
3、使用--from-literal创建ConfigMap
==使用--from-literal参数进行创建的示例如下:==
kubectl create configmap test-configmap --from-literal=loglevel=info --from-literal=appdatadir=/var/data
[root@master ~]# kubectl describe test-configmap
Name: test-configmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
appdatadir: 9 bytes
loglevel: 4 bytes
Events: <none>
容器应用对ConfigMap的使用有以下两种方法
- 通过环境变量获取ConfigMap中的内容
- 通过Volume挂载的方式将ConfigMap中的内容挂载为容器内部的文件或目录
Pod中使用ConfigMap
(1) 通过环境变量方式使用ConfigMap
首先我们需要创建ConfigMap
1.创建ConfigMap
[root@master configmap]# cat configmap-test-1.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: abcdocker-configmap
data:
keyinfo: www.abcdocker.com
abcdockerDir: /var/data
kubectl create -f configmap-test-1.yaml
2.创建pod进行引用
[root@master configmap]# cat configmap-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: abcdocker-pod
spec:
containers:
- name: configmap-pod
image: busybox
command: [ "/bin/sh", "-c", "env | grep config" ]
env:
- name: configmapPod
valueFrom:
configMapKeyRef:
name: abcdocker-configmap
key: keyinfo
- name: configmapDir
valueFrom:
configMapKeyRef:
name: abcdocker-configmap
key: abcdockerDir
restartPolicy: Never
==================相关参数解释===================
env:
- name: configmapPod ##定义环境变量名称
valueFrom: #key "keyinfo对应的值"
configMapKeyRef: name: abcdocker-configmap ##环境变量的值取自哪(上面创建的configmap名称)
key: keyinfo #configmap里对应的key
- name: configmapDir
valueFrom:
configMapKeyRef:
name: abcdocker-configmap
key: abcdockerDir
==================================================
kubectl create -f configmap-pod.yaml
验证
使用命令查看所有Pod
[root@master configmap]# kubectl get pod --show-all
Flag --show-all has been deprecated, will be removed in an upcoming release
NAME READY STATUS RESTARTS AGE
abcdocker-pod 0/1 Completed 0 3m
从kubernetes1.6开始,引用了一个新的字段envFrom
实现Pod环境内将ConfigMap中所有定义的key=value自动生成为环境变量
[root@master configmap]# cat configmap-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: abcdocker-pod
spec:
containers:
- name: configmap-pod
image: busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: abcdocker-configmap ##根据configmap中自动生成key=value环境变量
restartPolicy: Never
通过这个定义,在容器内部将会自动生成如下环境配置 需要说明的是,环境变量的名称手POSIX命名规范([a-zA-Z][a-zA-Z0-9])约束,不能以数字开头。如果包含非法字符,则系统将跳过该条环境变量的创建,并记录一个Event来描述环境变量无法生成,但不阻止Pod的启动
(2) 通过volumeMount使用ConfigMap
在本例子中包含了1个配置文件的定义 server.xml
1.创建ConfigMap
[root@master configmap]# cat configmap-tomcat-server.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: tomcat-server-config
data:
server.xml: |
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
<Listener className="org.apache.catalina.core.JasperListener" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="500" minSpareThreads="50" prestartminSpareThreads="true" />
<Connector executor="tomcatThreadPool" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443"
enableLookups="false"
maxPostSize="10485760"
URIEncoding="UTF-8"
disableUploadTimeout="true"
maxConnections="10000"
SSLEnabled="false"/>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Context path="" docBase="/tomcat/webapps" debug="0" reloadable="true" crossContext="true"/>
</Engine>
</Service>
</Server>
查看
[root@master configmap]# kubectl get configmaps tomcat-server-config
NAME DATA AGE
tomcat-server-config 1 13s
查看详细信息
[root@master configmap]# kubectl describe configmaps tomcat-server-config
Name: tomcat-server-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
server.xml:
----
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener
.....
2. 引用ConfigMap
在Pod中的定义,将文件以mount挂载到容器内部定义的目录中去。Pod配置文件如下
[root@master configmap]# cat test.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: abcdocker-pod
spec:
replicas: 1
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- image: busybox
imagePullPolicy: IfNotPresent
name: tomcatpod
volumeMounts:
- mountPath: /tmp/server.xml
name: serverxml
subPath: server.xml
ports:
- containerPort: 8080
command: ["tail", "-f", "/dev/null"]
volumes:
- name: serverxml
configMap:
name: tomcat-server-config
items:
- key: server.xml
path: server.xml
kubectl create -f test.yaml
===================参数解释===============
volumeMounts:
- mountPath: /tmp/server.xml ##挂在到容器内的目录
name: serverxml #挂载名称(需要和volume的名称对应上)
subPath: server.xml #不加subPath会替换整个目录
ports:
- containerPort: 8080
command: ["tail", "-f", "/dev/null"]
volumes:
- name: serverxml #volumemount名称
configMap:
name: tomcat-server-config #创建的configmap名称
items:
- key: server.xml #对应的key
path: server.xml #挂载到目录的key名称
####################################
需要注意的是,不可以光mount挂载,需要执行命令让容器在前台运行!
验证 登陆容器可以在tmp目录下看到我们的server.xml
如果在引用ConfigMap时不指定items,则使用volumeMount方式在容器内的目录中为每个item生成一个文件夹为key的文件
[root@master configmap]# cat test_vo.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: abcdocker-pod1
spec:
replicas: 1
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- image: busybox
imagePullPolicy: IfNotPresent
name: tomcatpod
volumeMounts:
- mountPath: /tmp/server.xml
name: serverxml
subPath: server.xml
ports:
- containerPort: 8080
command: ["tail", "-f", "/dev/null"]
volumes:
- name: serverxml
configMap:
name: tomcat-server-config
ConfigMap小结 使用ConfigMap的限制条件如下
- ConfigMap必须在Pod之前创建
- ConfigMap受Namespace限制,只有处于相同Namespace中的Pod可以引用它
- ConfigMap中的配额管理还未能实现
- Kubelet只可以支持可以被API Server管理的Pod使用ConfigMap。kubelet在本Node上通过 --manifest-url或--config自动创建的静态Pod将无法引用ConfigMap
- 在Pod对ConfigMap进行挂载
volumeMount
操作时,容器内部职能挂载"目录",无法挂载为文件。在挂载到容器内部后,目录中将包含ConfigMap定义的每个item,如果该目录下原来还有其他文件,则容器内的该目录将会被挂载的ConfigMap覆盖。如果应用程序需要保留原来的其他文件,则需要进行额外的处理。可以将ConfigMap挂载到容器内部的临时目录,再通过启动脚本将配置文件复制或者链接到(cp link)应用所用的实际配置目录下 - 需要注意的是,容器不可以光mount挂载,需要执行命令让容器在前台运行!
- 需要在挂载下面添加subPath,否则将会替换整个目录