第一个Pod与私有仓库
创建 Pod
在执行机上创建 nginxPod.yaml,执行 kubectl create -f nginxPod.yaml ,将返回创建成功。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.13
ports:
- containerPort: 80
若遇到错误:
... No API token found for service account “default”
这是因为 apiserver 启用了ServiceAccount插件,把他删除重启就可以了
截屏2022-03-15 下午9.53.50.png
查看 pod 信息
kubectl get pods # 查看列表
kubectl get pod nginx -o wide # 查看单个 pod 信息,-o wide 输出了 node 节点信息和 IP 地址
kubectl describe pod nginx # 查看更详细的信息
Untitled.png
Untitled1.png
# describe 结果:
Name: nginx
Namespace: default
Node: k8s-node1/172.16.156.129
Start Time: Mon, 14 Mar 2022 18:58:21 +0800
Labels: app=web
Status: Pending
IP:
Controllers: <none>
Containers:
nginx:
Container ID:
Image: nginx:1.13
Image ID:
Port: 80/TCP
State: Waiting
Reason: ContainerCreating
Ready: False
Restart Count: 0
Volume Mounts: <none>
Environment Variables: <none>
Conditions:
Type Status
Initialized True
Ready False
PodScheduled True
No volumes.
QoS Class: BestEffort
Tolerations: <none>
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
8h 8h 7 {kubelet k8s-node1} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"
8h 8h 65 {kubelet k8s-node1} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \\"registry.access.redhat.com/rhel7/pod-infrastructure:latest\\""
15m 15m 1 {default-scheduler } Normal Scheduled Successfully assigned nginx to k8s-node1
拉取镜像证书错误:更改 docker 地址
通过信息,我们看到当前 pod 中没有启动起来容器,从 describe 的详细信息我们可以看到详细的错误:
ErrImagePull: "image pull failed for [registry.access.redhat.com/rhel7/pod-infrastructure:latest](http://registry.access.redhat.com/rhel7/pod-infrastructure:latest), this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"
错误是因为拉取镜像的时候发现证书错误,经过查看,本地此证书是个软链接,且源文件不存在。
但从这个地址拉镜像是根据配置文件 /etc/kubenetes/kubelet 中的 KUBELET_POD_INFRA_CONTAINER 字段指定的。(pod 基础架构容器)
可以通过 docker search pod-infrastructure 来搜索此容器。选择与之一致的 Name(如: docker.io/meitham/pod-infrastructure ) 进行替换此配置。更新配置后重启 kubelet,稍等片刻会自动从新地址拉取镜像。可通过 describe 信息持续观察。不过这个问题的终极方案应该是用私有仓库来解决,当前知道这个问题的原因就好。
拉取镜像 io timeout:镜像加速
如果换了镜像后,出现错误 i/o timeout。可以查询一下镜像加速的方法。(不通 docker 版本可能方法不一样)
教程中是更改 docker 配置文件 /etc/sysconfig/docker 的 OPTIONS: `
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false --registry-mirror=https://registry.docker-cn.com --insecure-registry=172.16.156.128:5000'
# --insecure-registry 是用于私有仓库的地址的,后面会讲到
最后重启 docker ...
删除 Pod
kubectl delete pod nginx # 可加参数 --force --grace-period=0 强制删除
当删除Pod再创建的时候,新Pod很有可能会创建到另外一个节点,这时候会重新从网络上拉取镜像,会造成不必要的流量浪费以及长时间等待(节点可能很多)。解决方法是:创建一个私有仓库。(见下节)
更新 pod
kubectl apply pod -f xxx.yaml # 似乎不能加容器
pod 资源介绍
在 pod 所在的 node 节点上可通过 docker ps 看到启动的 docker。
刚刚启动的 nginx ID 为 63005b3fcb59 :
[root@k8s-master ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
63005b3fcb59 nginx:1.13 "nginx -g 'daemon ..." 21 hours ago Up 21 hours k8s_nginx.78d00b5_nginx_default_7764e0f3-a3d7-11ec-ac5e-000c295f166a_9ec846f8
fee040216725 docker.io/meitham/pod-infrastructure:latest "/usr/bin/pod" 21 hours ago Up 21 hours k8s_POD.7d850596_nginx_default_7764e0f3-a3d7-11ec-ac5e-000c295f166a_ae9db581
384ea5af6847 registry "/entrypoint.sh /e..." 21 hours ago Up 21 hours 0.0.0.0:5000->5000/tcp registry
[root@k8s-master ~]#
[root@k8s-master ~]# docker inspect 63005b3fcb59 | grep -i ipaddress
"SecondaryIPAddresses": null,
"IPAddress": "",
[root@k8s-master ~]# docker inspect 63005b3fcb59 | grep -i network
"NetworkMode": "container:fee0402167252211cb6e46c56338996a9967e9c4873c3b4654a6175a19984178",
"NetworkSettings": {
"Networks": {}
以上命令,可看到 nginx docker 没有 ip 地址,而他用的网络是和 container:fee04... 共用同一个网络的。而 fee04... 正是 pod-infrastructure 这个容器。
k8s 创建一个 pod 资源,会控制 docker 创建至少两个容器,一个是业务容器,一个是 pod 容器。而这个 pod 容器,正是定制好支持 k8s 自我修复、服务发现、负载均衡、自动部署/回滚、弹性伸缩 等功能。
创建两个容器的pod
可通过 kubectl explain pod 来查看 pod 资源的 yaml 可以配置什么字段。explain 命令支持层级关系,如 kubectl explain pod.spec.containers.command
给之前的 yaml 添加另一个容器 busybox
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: web
spec:
containers:
- name: nginx
image: 172.16.156.128:5000/nginx:1.13
ports:
- containerPort: 80
- name: busybox
image: 172.16.156.128:5000/busybox:latest
imagePullPolicy: IfNotPersent
command: ["sleep", "3600"]
ports:
- containerPort: 80
imagePullPolicy: IfNotPersent 是用于当本地有此版本的镜像的时候,不再从仓库中拉镜像而直接使用本地的。如果不设置的话,默认的策略是 always 就会总是从仓库中拉镜像。
重启此 pod 资源,用 apply 命令时提示重启失败(好像是因为加了 container),所以先删除,再重新创建。重新创建后发现,创建失败。通过 describe 命令查看到具体错误信息是用的 https 命令。更改 docker 配置的 OPTIONS 选项后重启 docker systemctl daemon-reload (docker.service 更改后就需要用这个命令重启)。稍等片刻后成功
错误信息是:
ErrImagePull: "Get https://172.16.156.128:5000/v1/_ping: http: server gave HTTP response to HTTPS client"
所加的 OPTIONS 配置是:
# /etc/sysconfig/docker
# Modify these options if you want to change the way the docker daemon runs
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false --registry-mirror=https://registry.docker-cn.com --insecure-registry=172.16.156.128:5000'
创建私有仓库
上节说过,当每次启动镜像都从外网拉取的话,对网络带宽消耗很大,尤其是在节点多的时候成本不可忽略。这个问题的终极方案就是创建私有仓库:当下载下来资源后,保存到自己的私有仓库。
私有仓库可以是 docker 官方提供的 registry 也可以是 Harbor。这里使用 registry。
registry 是个镜像,可以直接 pull 下来
截屏2022-03-15 下午11.27.10.png
docker pull docker.io/registry # 拉取 registry 做私有仓库
docker run -d -p 5000:5000 --restart=always --name registry \
-v /opt/myregistry:/var/lib/registry registry # 启动 registry
# 映射端口 5000;名称为 registry;映射目录;
传镜像:
- 打tag
docker tag docker.io/meitham/pod-infrastructure:latest 172.16.156.128:5000/pod-infrastructure:latest
- push 到私有仓库
docker push 172.16.156.128:5000/pod-infrastructure:latest
push 出错
错误 ****http: server gave HTTP response to HTTPS client****
原因:Docker自从1.3.X之后docker registry交互默认使用的是HTTPS。
解决:以下信息到/etc/docker/daemon.json中:{ "insecure-registries": [ "192.168.220.128:5000" ] }然后重启 docker:
systemctl daemon-reload
重试 push 操作。成功。
同样,推送一下 nginx 的容器:
[root@k8s-master ~]# docker tag docker.io/nginx:1.13 172.16.156.128:5000/nginx:1.13
[root@k8s-master ~]# docker push 172.16.156.128:5000/nginx:1.13
The push refers to a repository [172.16.156.128:5000/nginx]
7ab428981537: Pushed
82b81d779f83: Pushed
d626a8ad97a1: Pushed
1.13: digest: sha256:e4f0474a75c510f40b37b6b7dc2516241ffa8bde5a442bde3d372c9519c84d90 size: 948
[root@k8s-master ~]#
推送成功后将 pod 的 yaml 的镜像地址改为私有镜像的地址,完整如:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: web
spec:
containers:
- name: nginx
image: 172.16.156.128:5000/nginx:1.13
ports:
- containerPort: 80
查看私有仓库中镜像命令以及查看某镜像所有版本命令
# curl http://192.168.208.130:5000/v2/_catalog {"repositories":["alpine","fs-svr","kubernetes-dashboard-amd64","pod-infrastructure"]} # curl http://192.168.208.130:5000/v2/fs-svr/tags/list {"name":"fs-svr","tags":["0.0.1","0.0.2"]}
杂记
正好遇到 dev 环境集群有问题没人修,我硬着去定位了下,记录一下没有完整逻辑的过程,以后有经验了再补充。
背景:某假期之后第一天,dev 环境集群挂了,半天后有人把集群启动起来了说 OK 了,但集群中所有的服务还是挂的,无法访问。于是开始自己定位。
经过 describe 初步判断,已经 Running 状态的服务都是在本地有镜像的服务(有一条日志但没记录)。
通过任意一个没启动的微服务的 describe 信息看到所有启动服务时访问 harbor 502 了。通过这个定位到是 harbor 私有库有问题了。
image.png
image.png
通过 kubectl describe pod/harbor-core-6fb679f468-p7jpb -n harbor 查看到 harbor-core 服务启动异常。
Warning Unhealthy 18m (x70 over 63m) kubelet Readiness probe failed: Get "http://10.244.2.80:8080/api/v1/stats": dial tcp 10.244.2.80:8080: connect: connection refused
通过 kubectl logs pod/harbor-core-6fb679f468-p7jpb -n harbor 查看到日志是访问 harbor-redis 异常。
2022-04-06T08:04:54Z [ERROR] [/lib/cache/cache.go:110]: failed to ping redis://harbor-redis:6379/0?idle_timeout_seconds=30, retry after 10s : dial tcp 10.100.119.61:6379: connect: connection refused
直接删除了 redis 等它重启之后就好了: kubectl delete pod/harbor-redis-0 -n harbor --force 。(这里没有定位 redis 中有什么问题。)
截屏2022-03-15 下午9.53.50.png