在 K8S 中使用阿里云 ACR 镜像并调试容器

Published: 2023-08-02

Tags: k8s

本文总阅读量

构建 Alpine + Supervisor 基础镜像

Dockerfile

FROM alpine:3.18

RUN apk add --update supervisor && rm  -rf /tmp/* /var/cache/apk/*

ENTRYPOINT ["supervisord", "--nodaemon", "--configuration", "/etc/supervisord.conf"]

构建

$ docker build -t supine .

推送镜像

# 登录
$ docker login --username=your-name instance7-registry.cn-beijing.cr.aliyuncs.com

# 打 Tag
$ docker tag supine:latest instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/supine:1.0.0

# 推送
$ docker push instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/supine:1.0.0

注意事项

  1. docker login 登录的时候提示输入的密码非阿里云账号密码,可以在「实例管理」-「访问凭证」处进行设置。
  2. 如果是阿里云 ECS 机器访问镜像,可以使用内网地址,另外设置不可变镜像后,重复推送回失败。

命令行拉取镜像

$ docker pull instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/supine:1.0.0

从 K8S 中拉取镜像

配置密钥

有两种方式,一种是创建后在配置文件中指定密钥,另外一种是绑定在命名空间上,这样无需在配置文件中指定。

$ kubectl create secret docker-registry registry-secret --docker-server=instance7-registry.cn-beijing.cr.aliyuncs.com --docker-username=your-name --docker-password=your-passwd 

绑定在命名空间

$ kubectl create secret docker-registry registry-secret --docker-server=instance7-registry.cn-beijing.cr.aliyuncs.com --docker-username=your-name --docker-password=your-passwd  -n default

生成测试 Pod 配置

$ kubectl run test --image=instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/sidecar:0.0.1 --restart=Never --dry-run=client -o yaml > pod.yaml

在配置上补充密码

我这里使用的是第一种方式,未绑定到整个命名空间,所以需要在配置中指定 Secrets

spec:
  imagePullSecrets:
  - name: registry-secret

创建 Pod

$ kubectl apply -f pod.yaml

查看详细输出

可以使用 kubectl get pod test 查看 Pod 状态,如果拉取成功,则会显示 Complated 状态,否则是用如下命令查看详细信息

kubectl describe pod test

输出节选

  Warning  Failed     12s (x2 over 25s)  kubelet            Failed to pull image "instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/sidecar:0.0.1": rpc error: code = Unknown desc = failed to pull and unpack image "instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/sidecar:0.0.1": failed to resolve reference "instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/sidecar:0.0.1": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed

这是未指定密钥时的报错,问题修复后,再次 apply 配置。

需要注意:在测试期间,镜像每次都打同一个 Tag,K8S 中会缓存导致新制作的镜像使用不上。

Normal  Pulled     76s   kubelet            Container image "instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/sidecar:0.0.1" already present on machine

Pod 含有两个容器的示例

这里列出的配置仅作参考,所描述的场景是 Pos 启动时首先使用 initContainers 拉取 config-sidecar 镜像运行,它用来拉取配置,拉取成功后退出,而后启动 diamond 服务,在同一个 Pod 中,可以通过 volumeMounts 让不同容器间共享资源。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: diamond-sidecar
spec:
  replicas: 1
  selector:
    matchLabels:
      app: diamond-sidecar
  template:
    metadata:
      labels:
        app: diamond-sidecar
    spec:
      imagePullSecrets:
      - name: registry-secret
      initContainers:
      - name: config-sidecar
        image: instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/sidecar:0.0.2
        command: ["./config_sidecar.sh"]
        terminationMessagePolicy: FallbackToLogsOnError
        volumeMounts:
        - name: config-volume
          mountPath: /config
      containers:
      - name: diamond
        image: instance7-registry.cn-beijing.cr.aliyuncs.com/appserver/diamond:1.5.27
        volumeMounts:
        - name: config-volume
          mountPath: /config
        resources:
          limits:
            cpu: "256m"
            memory: "256Mi"
      volumes:
      - name: config-volume
        emptyDir: {}

进入到容器内部

最后,如果我们需要到容器内部确认服务状态或配置是否正确被放置,可以使用如下命令进入到容器内部。

# kubectl exec -it <pod_name> -c <container_name> -- bash
# 如果使用的 alpine 基础镜像,那么应用 sh 而非 bash
$ kubectl exec -it diamond-sidecar-689d756489-tjsdk -c diamond -- sh