k8s实验一 启动单个 NginxPod 并映射端口
目录
比起 docker 容器,k8s 部署容器复杂一点,但是 k8s 可以更灵活地配置。
本文的实验尝试创建一个 nginx(版本1.19.0) 应用,并映射容器的80端口,实现外网通过32080、内网通过2080端口访问应用。
如果是用 docker 实现
用 docker 就非常简单
docker run -p 32080:80 nginx:1.19.0
此时外网可以通过 32080 端口访问 nginx 应用(无防火墙)。
接下来部署 k8s,k8s 常用配置文件来操作,类似于 docker-compose,配置文件比指令操作可以更详细地描述资源。编写完配置文件后,执行 kubectl apply -f <文件>
即可交给k8s解析。
编写配置文件,部署 nginx Pod
# Source: pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: examplepod
labels:
e1podlabel: e1podvalue
app: exampleapp
spec:
containers:
- name: e1container
image: nginx:1.19.0
imagePullPolicy: IfNotPresent
# Source: pod.yaml
# 配置文件用到的解析版本,v1即可。用`kubectl api-versions`可以查看所有的 apiVersion。
apiVersion: v1
# 创建的资源类型,创建 Pod 就写 Pod。
kind: Pod
# 元数据,用来标识的资源的属性。比如资源名称
metadata:
# 资源的名称。
name: examplepod
# 资源的标签,标签可以自定义。
labels:
# 示例的自定义标签 e1podlabel。
e1podlabel: e1podvalue
# 示例的另一个自定义标签 app。
app: exampleapp
# 描述 Pod 的组成。
spec:
# 该 Pod 运行需要哪些容器
containers:
# 容器名称,重名也没问题
- name: e1container
# 容器用到的镜像,相当于 docker-compose 的镜像名
image: nginx:1.19.0
# 如何拉取这个镜像,IfNotPresent(找不到再拉取),Always(每次创建都拉取)
imagePullPolicy: IfNotPresent
详细字段说明
-
apiVersion
配置文件用到的解析版本,v1即可。用kubectl api-versions
可以查看所有的 apiVersion。 -
kind
创建的资源类型,创建 Pod 就写 Pod。 -
metadata
元数据,用来标识的资源的属性。比如资源名称 -
metadata.name
元数据中,资源的名称。 -
metadata.labels
元数据中,资源的标签,标签可以自定义。 -
metadata.labels.e1podlabel
元数据中,示例的自定义标签 e1podlabel。 -
metadata.labels.app
元数据中,示例的另一个自定义标签 app。 -
spec
资源描述,描述 Pod 的组成部分。 -
spec.containers
该 Pod 运行需要哪些容器。 -
spec.containers.name
容器名称,重名也没问题。 -
spec.containers.image
容器用到的镜像,相当于 docker-compose 的镜像名。 -
spec.containers.imagePullPolicy
如何拉取这个镜像,简要说下值,默认是 Always,每次创建Pod都重新拉取镜像,所以为了节省流量或私有需求,这里用IfNotPresent
,找不到再拉取。Never
不拉取,直接用本地,如果本地也没有镜像,则报错。IfNotPresent
如果本地已有镜像,则不拉取。本地没有再拉取。Always
总是拉取镜像再运行。
关于
imagePullPolicy
的详细解释: 提前拉取镜像
配置文件写完后,apply 即可:
kubectl apply -f pod.yaml
编写配置文件,部署端口映射服务(Service)
k8s 服务是给容器提供网络服务的,正常情况下Pod跑在容器里,网络是分离的,对Pod部署了服务后,外部网络就可以访问Pod了。以 docker 为例,服务类似于端口映射(-p参数)。
# Source: svc.yaml
apiVersion: v1
kind: Service
metadata:
name: examplesvc
spec:
type: NodePort
selector:
app: exampleapp
ports:
- protocol: TCP
port: 2080
targetPort: 80
nodePort: 32080
# Source: svc.yaml
# 同上,解析配置文件需要的版本
apiVersion: v1
# 资源类型,服务资源为 Service
kind: Service
# 元数据
metadata:
# 服务的名称
name: examplesvc
# 服务的描述
spec:
# 服务发布类型,常用 ClusterIP(集群内网访问) NodePort(外网也能访问) LoadBalancer(负载均衡)
type: NodePort
# 服务按标签查找Pod,标签匹配就给该 Pod 发布端口
selector:
# 带有标签 app: exampleapp 的 Pod 将被发布端口
app: exampleapp
# 发布哪些端口
ports:
# 发布一个 TCP 端口
- protocol: TCP
# 集群内网访问的端口
port: 2080
# Pod 中的端口
targetPort: 80
# 外部访问的端口
nodePort: 32080
详细字段说明
-
apiVersion
同上,解析配置文件需要的版本。 -
kind
资源类型,服务资源为 Service。 -
metadata
元数据。 -
metadata.name
该服务的名称。 -
spec
该服务的描述。 -
spec.type
服务发布类型,常用以下几种类型,默认是ClusterIP
。ClusterIP
发布到集群内网,就是只能在集群机器之间访问,如果k8s是单机,则等于只能在本机访问。NodePort
不仅内网,外网也能访问。本实验开放外网访问。LoadBalancer
关于
type
的详细解释: 发布服务(服务类型) -
spec.selector
标签选择器,很重要!服务是按标签查找Pod的。部署服务的时候,指定Pod的标签,服务就会查找每个Pod有没有这个标签,有的话,给这些Pod提供端口映射。上文的Pod已经配置了标签app: exampleapp
,而该服务仅要求标签app: exampleapp
,则该服务可以正确找到到上文的Pod,打开端口映射了。 -
spec.ports
想要配置的端口 -
spec.ports.protocol
端口协议,TCP或UDP。 -
spec.ports.port
集群内网访问用的端口,本实验用 2080。 -
spec.ports.targetPort
最终转发到Pod的哪个端口,Pod中的Nginx跑80端口,所以是80。 -
spec.ports.nodePort
外网访问用的端口,本实验用 32080。
配置完了,apply 即可:
kubectl apply -f svc.yaml
检查运行结果
至此本实验的部署工作已经完成,接下来是查看运行状态。
查看运行的 Pod
kubectl get pod
查看 Pod 详细信息
# 格式: kubectl describe pod <Pod名称>
kubectl describe pod examplepod
查看 Pod 日志
# 格式: kubectl logs <Pod名称>
kubectl logs examplepod
# 一直查看日志,直到 CTRL+C
kubectl logs -f examplepod
查看部署的服务
kubectl get service
kubectl get svc
查看服务详细信息
kubectl describe service
kubectl describe svc
尝试在集群访问
kubectl get svc
可以看到部署的服务,其中有ClusterIP,拿着这个IP,在集群的任何一台机器都可以访问到该服务映射的端口。
# 在集群的任何一台机器执行
curl <ClusterIP>:2080
尝试在外网访问
curl <外网IP>:32080
随时可以关闭端口映射服务
不同于docker,k8s部分资源都可以独立地关闭,只是依赖它的资源无法使用而已。
这也是撰写部署Pod和Service的配置文件时,写完了可以先运行的原因。
k8s 按照资源名称操作。
删掉本实验的端口映射服务
# 任意一种执行都可, service 和 svc 等同
kubectl delete service examplesvc
kubectl delete svc examplesvc
删掉后,集群和外网都无法访问了。
重新部署本实验的端口映射
kubectl apply -f svc.yaml
清理部署资源
实验结束,总共创建了2个资源: Pod、Service。这些资源都有名称,可以用名称删除它们。
kubectl delete pod examplepod
kubectl delete svc examplesvc