kubernetes入门篇之创建一个nginx容器
上几篇讲了部署master和worker node 及网络插件calico, 现在开始实际运行一个容器。
1. 新建nginx.yaml
文件
方式1:直接创建一个pod 和一个 service,一般不直接这样创建,该方式仅适用于测试或学习
apiVersion: v1
kind: Pod # 资源对象类型 为pod
metadata:
name: nginx
namespace: dev # 指定命令空间, 不然默认 default 命令空间
labels: # 标签
app: nginx
spec: # 属性
containers: # 容器
- name: nginx
image: nginx:1.27.4 # 镜像源
imagePullPolicy: IfNotPresent # 如果本地已有镜像,则不再拉取
ports:
- containerPort: 80 # 容器暴露的端口
---
apiVersion: v1
kind: Service # 资源类型为service
metadata: # 元数据
name: nginx-service
namespace: dev # 命令空间,默认default,不建议使用默认
spec:
type: NodePort # 类型,ClusterIP,NodePort, LoadBalancer
selector: # 选择器,选择哪个标签labels
app: nginx
ports: # 端口
- name: http
protocol: TCP # 协议类型 TCP,UDP,STCP
port: 80 # Service 的端口(集群内访问)
targetPort: 80 # 容器的端口(与 Pod 的 containerPort 一致)
nodePort: 30002 # 节点的访问端口(范围 30000-32767)
方式2: 使用 deployment 部署一个nginx service (推荐)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: dev
spec:
replicas: 1 # 副本数
selector: # 选择器
matchLabels:
app: nginx
template: # 模版
metadata: # 元数据
labels:
app: nginx
spec: # 属性
containers:
- name: nginx-container
image: nginx:1.27.4 # 镜像源
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: dev
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30002
type: NodePort
2. 新建命令空间
如果不新建命令空间,将使用默认的命令空间default
,这样不符合规范,容器一多也不方便管理
kubectl create namespace <name-space>
如: kubectl create namespace dev # 创建命名空间dev
上文使用的命令空间是dev
kubectl get ns #查看所有的命名空间
NAME STATUS AGE
default Active 8d
dev Active 12h
kube-node-lease Active 8d
kube-public Active 8d
kube-system Active 8d
test Active 11h
3. 在 worker node
拉取镜像到本地
nginx 官方镜像地址国内无法访问,如果本地没有就会从官方地址拉取,没有配置代理则会拉取失败。所以先下载到本地。
下载地址可以参数上篇calico
的地址:
ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.27.4-linuxarm64
ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.27.4-linuxarm64 docker.io/library/ngigx:1.27.4
4. 创建pod 和service
本文最后使用方式2创建,使用方式1时是测试镜像拉取出现的问题,后文会有记录。
kubectl create -f nginx.yaml # 首次创建
或
kubectl apply -f nginx.yaml # 更新
创建成功master节点查看:
[root@k8s-master test]# kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
nginx-deployment-f57fb66d4-tqmcj 1/1 Running 0 6h47m
[root@k8s-master test]# kubectl get service -n dev
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service NodePort 192.168.127.107 <none> 80:30002/TCP 6h48m
5. 访问
在master
或node
节点输入localhost:30002
集群外的机器输入IP:30002 也能访问,这里就不截图了。
6. 踩坑
6.1 镜像地址
imagePullPolicy
一定要配,不然就会从官方拉取,这里开始一直纳闷为啥本地拉取了镜像在创建pod
时,状态一直是ImagePullBackOff
。yaml
文件中是image:nginx:xxx
, 本地拉取镜像给镜像打tag
必须是docker.io/library/nginx:xxx
, 因为在拉取镜像时会在镜像名前默认添加docker.io/library/
的前缀,这点很坑。
使用方式1, 因为不了解 6.1, 所以在修改镜像地址时,写的 image: dev/nginx:1.27.4
,而tag
还是 docker.io/library/nginx:xxx
, 导致拉取镜像失败。
查看pod 的详细信息报:
Normal Scheduled 36s default-scheduler Successfully assigned dev/nginx to k8s-node1
Normal Pulled 5s (x5 over 35s) kubelet Container image "nginx:1.27.4" already present on machine
Warning Failed 5s (x5 over 35s) kubelet Error: failed to get image from containerd "sha256:9b1b7be1ffa607d40d545607d3fdf441f08553468adec5588fb58499ad77fe58": image "docker.io/dev/nginx:1.27.4": not found
6.2 nodeport 不存在
因为节点的访问端口设置的30002
, 所以在查看pod
和service
没问题后,在节点netstat -nlp | grep 30002
,哦豁,超出认知范围,竟然找不到端口。
不知道为啥,然后在浏览器瞎试了一把,发现步骤5竟然没问题。
然后去找了一下资料,是被iptables
转发了。
检查 iptables 规则(查找 30002 端口相关规则)
iptables -t nat -L KUBE-NODEPORTS -n --line-numbers | grep 30002
# 存在类似 KUBE-SVC-XXX tcp dpt:30002 的规则,说明流量通过 iptables 转发