一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
一、前言
为什么在一个pod上运行多个容器,而不是在一个容器上运行多个进程呢?
- 容器的设计原则就是一个容器运行一个进程(由父进程产生子进程的除外)
- 容器中有多个进程,根据日志进行系统排错变困难,难以管理不同进程的生命周期
- 一个应用程序使用多个容器可以实现进一步的解耦
多容器Pod的特征:
运行在一个pod节点上的多个容器,它们共享的资源有:
- 相同的
Linux命名空间(相同IP地址和端口空间,容器间互相访问) - 相同
IPC名称空间 - 可以使用相同的共享卷
使用场景:应用由一个主进程和一个/多个辅助进程组成。
二、Pod容器间的通信
通信主要3种方式:
Pod共享Volume- 进程间通信(
IPC) - 容器间网络通信
(1)Pod 共享 Volume
常见用法: 一个容器写日志或其它数据文件到共享目录中,其它容器从这个共享目录中读取数据。
Pod 中运行的多个容器可以共享 Pod 级别的存储卷 Volume,可以使用 emptyDir 类型的存储卷作为 Pod 内部的空目录,用于 Pod 中运行的多个容器间的数据共享。
举个例子:
一个pod包含两个容器:
tomcat容器,用于向app-logsvolume中写入日志文件busybox容器用于从app-logsvolume中读取日志文件并打印
- 创建
tomcat-busybox.yaml
tomcat容器在启动后会向/usr/local/tomcat/logs目录下写日志文件,而busybox容器就可以读取其中的日志文件
apiVersion: v1
kind: Pod
metadata:
name: tomcat-busybox-pod
spec:
containers:
- name: tomcat
image: tomcat
ports:
- containerPort: 8080
volumeMounts:
- name: app-logs
mountPath: /usr/local/tomcat/logs # 将共享卷 app-logs 挂载到 tomcat 容器内的 /usr/local/tomcat/logs 目录下
- name: busybox
image: busybox
command: ["sh", "-c", "tail -f /logs/catalina*.log"]
volumeMounts:
- name: app-logs
mountPath: /logs # 将共享卷 app-logs 挂载到 busybox 容器内的 /logs 目录下
volumes:
- name: app-logs
emptyDir: {}
- 执行创建
$ kubectl create -f tomcat-busybox.yaml
pod/tomcat-busybox-pod created
# 这里的 2/2 表示两个容器都启动成功了
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
tomcat-busybox-pod 2/2 Running 0 50s
- 查看创建过程
# 查看详细的创建过程(包括 Volumes 和 Events),可以看到两个容器依次被创建了起来
$ kubectl describe pod tomcat-busybox-pod
- 查看
busybox日志
busybox容器的启动命令tail -f /logs/catalina*.log通过kubelet logs命令查看busybox容器的输出内容busybox容器打印的是日志文件 /usr/local/tomact/logs/catalina..log 中的内容
$ kubectl logs tomcat-busybox-pod -c busybox
......
26-Sep-2019 09:56:26.653 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/docs]
26-Sep-2019 09:56:26.687 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/docs] has finished in [34] ms
26-Sep-2019 09:56:26.691 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
26-Sep-2019 09:56:26.702 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
26-Sep-2019 09:56:26.705 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 822 ms
- 查看
tomcat容器日志信息
$ kubectl exec -it tomcat-busybox-pod -c tomcat -- ls /usr/local/tomcat/logs
catalina.2019-09-26.log localhost_access_log.2019-09-26.txt
host-manager.2019-09-26.log manager.2019-09-26.log
localhost.2019-09-26.log
$ kubectl exec -it tomcat-busybox-pod -c tomcat -- tail /usr/local/tomcat/logs/catalina.2019-09-26.log
......
26-Sep-2019 09:56:26.653 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/docs]
26-Sep-2019 09:56:26.687 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/docs] has finished in [34] ms
26-Sep-2019 09:56:26.691 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
26-Sep-2019 09:56:26.702 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
26-Sep-2019 09:56:26.705 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 822 ms
- 删除
pod:kubectl delete pod xxx
(2)进程间通信(IPC)
一个 Pod 中的多个容器之间共享相同的 IPC 命名空间,所以它们互相之间可以使用标准进程间通信,比如:SystemV 信号系统或 POSIX 共享内存。
举个例子:
在一个pod中运行两个容器:
- 生产者
producer - 消费者
consumer
这两个容器都使用相同的镜像
ipc:
producer容器创建了一个标准的Linux消费队列,写一些随机的消息,最后写一个特殊的退出消息consumer容器打开相同的消费队列来读取消息,直到接收到退出消息。
- 创建
yaml配置文件
apiVersion: v1
kind: Pod
metadata:
name: ipc-test
spec:
containers:
- name: producer
image: registry-vpc.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/ipc:latest
command: ["./ipc", "-producer"]
- name: consumer
image: registry-vpc.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/ipc:latest
command: ["./ipc", "-consumer"]
restartPolicy: Never
-
执行创建:
kubectl create -f ipc-pod.yaml -
查看每个容器的日志
$ kubectl logs ipc-test -c producer
......
Produced: 9a
Produced: 21
Produced: c8
Produced: a
Produced: 76
$ kubectl logs ipc-test -c consumer
......
Consumed: 9a
Consumed: 21
Consumed: c8
Consumed: a
Consumed: 76
Consumed: done
(3)容器间网络通信
pod中的多个容器都可以通过localhost进行互相访问,因为它们都使用相同的网络名称空间。
举个例子:
在pod中创建两个容器:
nginx容器作为反向代理webapp容器运行一个简单的服务
配置
nginx文件通过 http 80端口访问请求会被转发到本地的 5000 端口上
- 在
nginx.conf配置文件写入
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream webapp {
server 127.0.0.1:5000;
}
server {
listen 80;
location / {
proxy_pass http://webapp;
proxy_redirect off;
}
}
}
- 使用
nginx.conf配置文件创建一个nginx-conf的ConfigMap
$ kubectl create configmap nginx-conf --from-file=/home/shiyanlou/nginx.conf
configmap/nginx-conf created
- 创建
pod文件
开放
nginx容器的 80 端口,webapp容器的5000端口没有开放的,不能被pod外部访问
apiVersion: v1
kind: Pod
metadata:
name: nginx-webapp-pod
labels:
app: http-service
spec:
containers:
- name: webapp
image: registry-vpc.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/webapp:latest
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: nginx-proxy-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: nginx-proxy-config
configMap:
name: nginx-conf
- 执行创建
pod资源对象
$ kubectl create -f nginx-webapp.yaml
pod/nginx-webapp-pod created
- 使用
NodePort服务暴露nginx-webapp-pod Pod
$ kubectl expose pod nginx-webapp-pod --type=NodePort --port=80
service/nginx-webapp-pod exposed
- 查看
nginx-webapp-pod所在的Node节点,并且查看nginx-webapp-pod服务开放的NodePort
$ kubectl get pod nginx-webapp-pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-webapp-pod 2/2 Running 0 7m7s 10.244.2.4 kube-node-1 <none> <none>
$ kubectl describe service nginx-webapp-pod
...
NodePort: <unset> 30889/TCP
...
- 通过
curl访问Node IP + NodePort地址
$ curl 10.192.0.3:30889
Hello world!