3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

containerdでcreator-ee v0.5.0+のイメージがpullできずにハマった話

Last updated at Posted at 2022-06-29

containerdでcreator-eeのv0.5.0+のイメージがpullに失敗するという事象が発生した。(KubernetesのコンテナランタイムがDockerからcontainerdに代わってから、初めてruntimeの挙動の差にハマった気がした)

containerdのコード読むよい機会だったので、コンテナイメージのpull周りを読みつつ、この件についてまとめてみた。今回の問題は既にコミュニティにより containerd - #7094 で修正されている。

背景

ローカルのDocker for Desktopでは問題なく動いていたが、Kubernetes上で動いているDrone1でcreator-ee2のv0.6.0のイメージを使うと何のエラーも出ずに停止する問題があった。

> sudo docker pull quay.io/ansible/creator-ee:v0.5.0
...
ff3ce4e37203: Pull complete
be34f4f093fc: Pull complete
Digest: sha256:4d21770ba05e0373ef6506df50eaebcf1586c4dbfffb728f52dfba08eb0dc222
Status: Downloaded newer image for quay.io/ansible/creator-ee:v0.5.0
quay.io/ansible/creator-ee:v0.5.0

> echo $?
0

確認したこと

  1. creator-eeのバージョンを二分探索したところ、v0.5.0+のイメージが動かないことが分かった

  2. droneはKubernetes上で動いているので該当pipelineのPodを確認したが、該当コンテナのログはUI上と同じく何も出力されておらず、Exit(2)になっていた

  3. droneを経由させずにKubernetes上で該当イメージを立ち上げたところ、イメージのpull時に権限エラーでレイヤーの展開に失敗していることが分かった

    Events:
      Type     Reason     Age                   From               Message
      ----     ------     ----                  ----               -------
      Normal   Scheduled  30m                   default-scheduler  Successfully assigned default/ee50 to demo-ladicle-w-default-a9d89c28-htgqp
      Normal   Pulling    27m (x4 over 30m)     kubelet            Pulling image "quay.io/ansible/creator-ee:v0.5.0"
      Warning  Failed     27m (x4 over 29m)     kubelet            Error: ErrImagePull
      Warning  Failed     27m (x6 over 29m)     kubelet            Error: ImagePullBackOff
      Normal   BackOff    5m17s (x94 over 29m)  kubelet            Back-off pulling image "quay.io/ansible/creator-ee:v0.5.0"
      Warning  Failed     19s (x10 over 29m)    kubelet            Failed to pull image "quay.io/ansible/creator-ee:v0.5.0": rpc error: code = Unknown desc = failed to pull and unpack image "quay.io/ansible/creator-ee:v0.5.0": failed to extract layer sha256:140b571c235813a8eb5ba7f5f474f8852eef0218d4e5efe99801351d4c76aa6b: operation not permitted: unknown
    
  4. 手元の環境でcontainerd(ctr)単体のイメージpullを試したが、同様のエラーで失敗するためkubernetes & 環境固有の問題ではないことが分かった

    $ sudo ctr image pull quay.io/ansible/creator-ee:v0.5.0
    ...
    layer-sha256:1cb646aa85f30788a51b53eda39160008325a7ae05b03050ba8b2726aee91549:    done           |++++++++++++++++++++++++++++++++++++++|
    layer-sha256:764ac4e7ad9bfa3a618b07693be79a7fd44b6a2fd35d497a7256458925219d33:    done           |++++++++++++++++++++++++++++++++++++++|
    elapsed: 56.0s                                                                    total:  540.1  (9.6 MiB/s)
    unpacking linux/amd64 sha256:4d21770ba05e0373ef6506df50eaebcf1586c4dbfffb728f52dfba08eb0dc222...
    INFO[0064] apply failure, attempting cleanup             error="failed to extract layer sha256:140b571c235813a8eb5ba7f5f474f8852eef0218d4e5efe99801351d4c76aa6b: operation not permitted: unknown" key="extract-661548272-faQw sha256:f5544d59a150fa51ce83f2fce9214393ff91001ccaaac6405d892a6dbb3ac4c7"
    ctr: failed to extract layer sha256:140b571c235813a8eb5ba7f5f474f8852eef0218d4e5efe99801351d4c76aa6b: operation not permitted: unknown
    
  5. containerdの特定バージョンの問題か確認するため、v1.6.4とv1.4.4で試したが同様のエラーが発生した

  6. Dockerでは動作し、containerdでは複数バージョンで失敗するためcontainerdに報告を上げた

原因と解決方法

ref: https://github.com/containerd/containerd/pull/7094
image.png

原因は、tarからファイルを展開3する際に、拡張属性を設定できないシンボリックリンクに対してsetxattrを実行し、そのままエラーを返したことだった。

ユーザ拡張属性はレギュラーファイルとディレクトリのみに設定できる4。しかし、公式のcreator-eeのコンテナイメージでは、シンボリックリンクの /etc/krb5.conf.d/crypto-policies tarヘッダ5にこの拡張属性情報が入っていた。containerdはこれを設定しようとして EPERM で失敗していた6

解決策として、上記PRではレギュラーファイルとディレクトリ以外に対しては EPERM を無視するように修正された。

https://github.com/containerd/containerd/blob/16992a4a2e5c86a91556f4c24e3fcded3a7cfd0d/archive/tar.go#L395-L401 より抜粋

func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header, reader io.Reader) error {
...
if strings.HasPrefix(key, paxSchilyXattr) {
	key = key[len(paxSchilyXattr):]
	if err := setxattr(path, key, value); err != nil { // ここでsymlinkに対するsetxattrがEPERMで失敗
		if errors.Is(err, syscall.ENOTSUP) {
			log.G(ctx).WithError(err).Warnf("ignored xattr %s in archive", key)
			continue
		}
		return err
	}
}

NOTE: docker(moby)の場合

全てのストレージドライバが xattrs をサポートしているわけではない。ということで、 EPERM (& ENOTSUP)エラーは全て無視する仕様になっている。

https://github.com/moby/moby/blob/b8b1e16fed062eb351608a0d608b7e90c4e1ddf1/pkg/archive/archive.go#L782-L790 より抜粋

var errors []string
for key, value := range hdr.Xattrs {
	if err := system.Lsetxattr(path, key, []byte(value), 0); err != nil {
		if err == syscall.ENOTSUP || err == syscall.EPERM {
			// We ignore errors here because not all graphdrivers support
			// xattrs *cough* old versions of AUFS *cough*. However only
			// ENOTSUP should be emitted in that case, otherwise we still
			// bail.
			// EPERM occurs if modifying xattrs is not allowed. This can
			// happen when running in userns with restrictions (ChromeOS).
			errors = append(errors, err.Error())
			continue
		}
		return err
	}
  1. Drone CI – Automate Software Testing and Delivery

  2. ansible/creator-ee: Ansible Execution environment targeted for content creators.

  3. (単純にtarを展開しているのではなく) OCIの Applying ChangeSets の仕様に基づき、ファイルやwhiteoutを展開先のディレクトリに適用している

  4. xattr(7) - Linux manual page のUser extended attributes参照 (実装はlinux/fs/xattr.c#L129)

  5. https://docs.studygolang.com/src/archive/tar/common.go#L191

  6. そもそも何故、拡張属性がシンボリックリンクに付いているのかはまだ分かっていない。creator-eeが提供しているpodman/dockerでそれぞれ自前ビルドしたイメージをpullしてみたが、その場合は問題なく展開できた。creator-eeのビルドオプションの関係なんだろうか。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?