第一个Pod与私有仓库

2022-03-21  本文已影响0人  Robin92

创建 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;映射目录;

传镜像:

  1. 打tag
docker tag docker.io/meitham/pod-infrastructure:latest 172.16.156.128:5000/pod-infrastructure:latest
  1. 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 中有什么问题。)

上一篇 下一篇

猜你喜欢

热点阅读