Kubernetes容器玩法全解析
1. 容器端口转发与网络模型
在Kubernetes系统中,Pod是基本的计算单元。为了更有效地使用Pod,我们先来了解容器端口转发以及Kubernetes的四种网络模型。
1.1 准备工作
为了演示四种网络模型的工作原理,我们将运行两个nginx Web应用。Docker Hub上nginx的默认端口是80,我们将通过修改nginx配置文件和Dockerfile,把端口从80改为8800,创建一个新的nginx Docker镜像。具体步骤如下:
1. 创建一个简单的nginx配置文件
nginx.conf
,监听8800端口:
# cat nginx.conf
server {
listen 8800;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
- 修改默认的nginx Dockerfile,将暴露端口从80改为8800,并添加配置文件:
# cat Dockerfile
FROM debian:jessie
MAINTAINER NGINX Docker Maintainers "docker-maint@nginx.com"
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys
573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
RUN echo "deb http://nginx.org/packages/mainline/debian/ jessie nginx" >>
/etc/apt/sources.list
ENV NGINX_VERSION 1.9.9-1~jessie
RUN apt-get update && \
apt-get install -y ca-certificates nginx=${NGINX_VERSION} && \
rm -rf /var/lib/apt/lists/*
COPY nginx.conf /etc/nginx/conf.d/default.conf
# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log
RUN ln -sf /dev/stderr /var/log/nginx/error.log
VOLUME ["/var/cache/nginx"]
EXPOSE 8800
CMD ["nginx", "-g", "daemon off;"]
- 使用Docker命令构建镜像:
# docker build -t $(YOUR_DOCKERHUB_ACCOUNT)/nginx_8800 .
- 推送镜像到Docker Hub仓库:
# docker push $(YOUR_DOCKERHUB_ACCOUNT)/nginx_8800
完成上述步骤后,你可以使用纯Docker命令运行容器:
docker run -d -p 8800:8800 msfuko/nginx_8800
使用
curl $IP:8800
,你应该能看到nginx的欢迎页面。如果你在Linux上运行,可以使用
ifconfig
命令查找
$IP
;如果你通过Docker machine在其他平台上运行,可以使用
docker-machine ip
命令。
1.2 四种网络模型
Kubernetes有四种网络模型,下面详细介绍:
-
容器到容器通信
:在一个Pod中创建两个nginx容器,分别监听80和8800端口。
# cat nginxpod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginxpod
spec:
containers:
-
name: nginx80
image: nginx
ports:
-
containerPort: 80
hostPort: 80
-
name: nginx8800
image: msfuko/nginx_8800
ports:
-
containerPort: 8800
hostPort: 8800
创建Pod:
# kubectl create -f nginxpod.yaml
使用
kubectl get pods nginxpod
查看Pod状态,使用
kubectl describe pod nginxpod
查看详细信息。登录到
kube-node1
,使用
docker ps
列出容器,使用
jq
作为JSON解析器检查容器的网络设置:
# docker inspect 3b467d8772f0 | jq '.[]| {NetworkMode: .HostConfig.
NetworkMode, NetworkSettings: .NetworkSettings}'
可以发现两个容器的网络模式都设置为映射容器模式,共享网络接口,因此它们彼此视为localhost。
-
Pod到Pod通信 :每个Pod都有自己的IP地址,使得Pod之间的通信变得容易。使用flannel作为覆盖网络,为每个节点定义不同的网段,每个数据包被封装成UDP数据包,使每个Pod IP可路由。
-
Pod到服务通信 :由于Pod可能会意外停止,其IP地址可能会改变。当为Pod或复制控制器暴露端口时,我们创建一个Kubernetes服务作为代理或负载均衡器。具体步骤如下:
1. 创建一个名为my-first-nginx的复制控制器:
# kubectl run my-first-nginx --image=nginx --replicas=2 --port=80
- 列出Pod,确保复制控制器创建了两个Pod:
# kubectl get pod
- 为Pod暴露端口80:
# kubectl expose rc my-first-nginx --port=80
-
使用
kubectl describe service my-first-nginx查看服务详细信息,服务类型为ClusterIP,虚拟IP为192.168.235.209,将流量分发到两个端点192.168.20.2:80和192.168.55.5:80。 -
kube-proxy守护进程在每个节点上作为网络代理工作,创建相应的iptables规则:
# iptables -t nat -L | grep my-first-nginx
你可以在目标节点上访问
localhost:43321
或在集群内访问
$nodeIP:43321
。
-
外部到内部通信
:可以使用外部负载均衡器(如GCE的ForwardingRules或AWS的ELB)或直接访问节点IP来设置外部到内部的通信。这里介绍直接访问节点IP的方法:
1. 创建一个名为my-second-nginx的复制控制器,有两个副本:
# kubectl run my-second-nginx --image=nginx --replicas=2 --port=80
- 以LoadBalancer类型暴露服务端口80:
# kubectl expose rc my-second-nginx --port=80 --type=LoadBalancer
-
使用
kubectl describe service my-second-nginx查看服务详细信息,服务有一个虚拟IP192.168.156.93和一个节点端口31150。 - 列出iptables规则,查看不同类型服务的差异:
# iptables -t nat -L | grep my-second-nginx
来自节点端口或ClusterIP的流量将通过负载均衡机制重定向到目标Pod。
2. 灵活使用容器:Job和Daemon Set
Pod是Kubernetes中最小的计算单元,通常由复制控制器管理并通过服务暴露。这里介绍两个新特性:Job和Daemon Set,它们可以使Pod的使用更加有效。
2.1 准备工作
- Job类型的Pod :Kubernetes Job中的Pod在完成工作后会直接终止。
- Daemon类型的Pod :Daemon类型的Pod会在每个节点上创建,作为系统守护进程长期运行。
需要注意的是,Daemon Set类型在默认API设置中是禁用的,需要启用才能进行测试。启用方法如下:
- 对于
init.d
服务脚本,在
hyperkube apiserver
或
kube-apiserver
命令后添加标签
--runtime-config=extensions/v1beta1/daemonsets=true
。
# cat /etc/init.d/kubernetes-master
(heading lines ignored)
:
# Start daemon.
echo $"Starting apiserver: "
daemon $apiserver_prog \
--service-cluster-ip-range=${CLUSTER_IP_RANGE} \
--insecure-port=8080 \
--secure-port=6443 \
--basic-auth-file="/root/ba_file" \
--address=0.0.0.0 \
--etcd_servers=${ETCD_SERVERS} \
--cluster_name=${CLUSTER_NAME} \
--runtime-config=extensions/v1beta1/daemonsets=true \
> ${logfile}-apiserver.log 2>&1 &
:
(ignored)
-
对于
systemd服务管理,在配置文件中添加标签作为可选参数。
# cat /etc/kubernetes/apiserver
(heading lines ignored)
:
# Add your own!
KUBE_API_ARGS="--cluster_name=Happy-k8s-cluster --runtime-
config=extensions/v1beta1/daemonsets=true"
设置标签后,删除
/tmp/kubectl.schema
目录,然后重启Kubernetes apiserver:
# rm -f /tmp/kubectl.schema
# service kubernetes-master restart
# systemd restart kube-apiserver
重启后,使用
curl http://localhost:8080/apis/extensions/v1beta1
检查Daemon Set是否已启用。
2.2 创建Job和Daemon Set
由于没有命令行界面来创建Job或Daemon Set,我们需要通过编写配置文件来构建这两种资源类型。
-
Pod作为Job
:Job类型的Pod适用于测试容器,如单元测试、集成测试或静态程序。以下是一个检查
ubuntu
镜像中安装包的Job模板:
# cat job-dpkg.yaml
apiVersion: extensions/v1beta1
kind: Job
metadata:
name: package-check
spec:
selector:
matchLabels:
image: ubuntu
test: dpkg
template:
metadata:
labels:
image: ubuntu
test: dpkg
owner: Amy
spec:
containers:
- name: package-check
image: ubuntu
command: ["dpkg-query", "-l"]
restartPolicy: Never
创建Job:
# kubectl create -f job-dpkg.yaml
使用
kubectl get job
和
kubectl get pod
验证Job和Pod的状态,使用
kubectl logs
获取结果,使用
kubectl describe job
查看详细信息。删除Job:
# kubectl stop job package-check
如果需要创建多个Pod来完成一个Job,可以添加
spec.completions
项指定Pod数量:
# cat job-dpkg.yaml
apiVersion: extensions/v1beta1
kind: Job
metadata:
name: package-check
spec:
completions: 3
template:
metadata:
name: package-check-amy
labels:
image: ubuntu
test: dpkg
owner: Amy
spec:
containers:
- name: package-check
image: ubuntu
command: ["dpkg-query", "-l"]
restartPolicy: Never
- Pod作为Daemon Set :如果创建了Kubernetes Daemon Set,定义的Pod将部署在每个节点上,确保每个节点上的运行容器占用相等的资源。以下是一个检查内存使用情况的Daemon Set模板:
# cat daemonset-free.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: ram-check
spec:
selector:
app: checkRam
version: v1
template:
metadata:
labels:
app: checkRam
owner: Amy
version: v1
spec:
containers:
- name: ubuntu-free
image: ubuntu
command: ["/bin/bash","-c","while true; do free; sleep 30; done"]
restartPolicy: Always
创建Daemon Set:
# kubectl create -f daemonset-free.yaml
使用
kubectl get ds
和
kubectl describe ds
查看Daemon Set的信息,使用
kubectl get pod
和
kubectl describe pods
查看Pod的信息,使用
kubectl logs
获取结果。删除Daemon Set:
# kubectl stop -f daemonset-free.yaml
# kubectl stop ds ram-check
如果只需要在特定节点上运行Daemon Set,可以先给节点打标签,然后在模板中使用
spec.template.spec.nodeSelector
进行选择:
# kubectl label nodes kube-node3 runDS=ok
# cat daemonset-free.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: ram-check
spec:
selector:
app: checkRam
version: v1
template:
metadata:
labels:
app: checkRam
owner: Amy
version: v1
spec:
nodeSelector:
runDS: ok
containers:
- name: ubuntu-free
image: ubuntu
command: ["/bin/bash","-c","while true; do free; sleep 30; done"]
restartPolicy: Always
总结
通过本文,我们学习了Kubernetes的容器端口转发和四种网络模型,以及如何使用Job和Daemon Set灵活管理Pod。这些知识可以帮助你更好地在Kubernetes中部署和管理容器化应用。
Kubernetes容器玩法全解析
3. 网络模型的深入理解与应用场景
3.1 网络模型对比分析
为了更清晰地理解Kubernetes的四种网络模型,我们可以通过以下表格进行对比:
| 网络模型 | 特点 | 应用场景 |
| — | — | — |
| 容器到容器通信 | 同一Pod内的容器共享网络接口,视为localhost,通信高效 | 适合紧密耦合的应用组件,如Web应用和其缓存服务 |
| Pod到Pod通信 | 每个Pod有独立IP,通过覆盖网络实现通信 | 不同功能模块的Pod之间通信,如前端和后端服务 |
| Pod到服务通信 | 服务作为代理或负载均衡器,处理Pod IP变化问题 | 确保服务的高可用性和负载均衡,如多个副本的Web服务 |
| 外部到内部通信 | 通过外部负载均衡器或节点IP实现外部访问 | 让外部用户能够访问Kubernetes集群内的服务,如Web应用对外提供服务 |
3.2 网络模型的工作流程
下面是一个mermaid格式的流程图,展示了Pod到服务通信的工作流程:
graph LR
A[客户端请求] --> B(Kubernetes服务虚拟IP)
B --> C(kube - proxy)
C --> D{负载均衡}
D --> E1(Pod1)
D --> E2(Pod2)
D --> E3(Pod3)
从流程图可以看出,客户端的请求首先到达Kubernetes服务的虚拟IP,然后由
kube - proxy
进行处理,通过负载均衡机制将流量分发到相应的Pod。
4. Job和Daemon Set的高级应用与注意事项
4.1 Job的高级应用
- 定时任务 :结合Kubernetes的CronJob特性,可以实现定时执行Job。例如,每天凌晨执行数据备份任务。
# cat cronjob-backup.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: data - backup
spec:
schedule: "0 0 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup - container
image: backup - image
command: ["backup - script"]
restartPolicy: OnFailure
创建CronJob:
# kubectl create -f cronjob - backup.yaml
- 任务依赖 :在某些情况下,Job之间可能存在依赖关系。可以通过编写脚本或使用第三方工具来实现任务的顺序执行。
4.2 Daemon Set的高级应用
- 节点监控 :在每个节点上部署监控容器,实时收集节点的性能指标,如CPU、内存、磁盘使用情况等。
# cat daemonset - monitor.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: node - monitor
spec:
selector:
app: monitor
version: v1
template:
metadata:
labels:
app: monitor
owner: Admin
version: v1
spec:
containers:
- name: monitor - container
image: monitor - image
command: ["monitor - script"]
restartPolicy: Always
创建Daemon Set:
# kubectl create -f daemonset - monitor.yaml
- 日志收集 :在每个节点上部署日志收集容器,将节点上的日志统一收集并发送到日志存储系统。
4.3 注意事项
-
Job
:Job的selector不能指向现有的Pod,避免将受复制控制器控制的Pod误用作Job。同时,Pod的重启策略应设置为
Never或OnFailure。 - Daemon Set :在启用Daemon Set之前,务必按照前面介绍的方法正确配置API服务器。另外,在选择节点运行Daemon Set时,要确保节点标签的准确性。
5. 总结与实践建议
5.1 总结
Kubernetes的容器管理功能强大,通过四种网络模型和Job、Daemon Set等特性,可以实现灵活高效的容器部署和管理。网络模型确保了容器之间、Pod之间以及与外部的通信顺畅,而Job和Daemon Set则满足了不同类型任务的需求。
5.2 实践建议
- 逐步实践 :初学者可以先从简单的网络模型和基本的Job、Daemon Set配置开始,逐步深入学习和实践。
- 监控与优化 :在实际应用中,要对容器和服务进行监控,根据性能指标进行优化,确保系统的稳定性和高效性。
- 参考官方文档 :Kubernetes官方文档提供了详细的技术说明和示例,是学习和实践的重要参考资料。
通过不断学习和实践,你将能够熟练掌握Kubernetes的容器管理技巧,为容器化应用的部署和运行提供有力支持。
超级会员免费看
707

被折叠的 条评论
为什么被折叠?



