sysnet4admin / _Book_k8sInfra

< 컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커 >
432 stars 173 forks source link

[ 3.1.3 ] pod create 불가한 문제 #33

Closed zenio7 closed 10 months ago

zenio7 commented 10 months ago
  • [ ] 초기화된(새로 설치) 노트북(또는 PC)
  • [ ] 책에서 제시한 프로그램과 동일한 버전 설치
  • [ ] 할리스(IP가 겹침)를 제외한 카페 또는 집에서 실행 ~ 자택에서 수행함
  • [ ] 2대 이상 동일하게 문제가 발생함 ~ 2대이상에서 테스트해보지 못했습니다.

[ 내용 ]

파트 3.1.3 의 nginx-pod.yaml 을 kubectl create 명령실행했을때 kubectl get pod의 상태가 ErrImage 이후 ImagePullBackoff 과정이 반복됩니다.

혹시나하여 docker pull nginx 해보니 missing signature key 에러발생하고요.

vagrant up 했을때 로그중에 w1-k8s: SSH username: vagrant w1-k8s: SSH auth method: private key w1-k8s: Warning: Connection reset. Retrying... w1-k8s: Warning: Connection aborted. Retrying... w1-k8s: Warning: Connection reset. Retrying... w1-k8s: Warning: Connection aborted. Retrying... w1-k8s: Warning: Connection reset. Retrying... w1-k8s: Warning: Connection aborted. Retrying... w1-k8s: w1-k8s: Vagrant insecure key detected. Vagrant will automatically replace w1-k8s: this with a newly generated keypair for better security. w1-k8s: w1-k8s: Inserting generated public key within guest... w1-k8s: Removing insecure key from the guest if it's present... w1-k8s: Key inserted! Disconnecting and reconnecting using new SSH key... ==> w1-k8s: Machine booted and ready!

이런 내용이찍히던데 해당로그와 관련이 있는건지 윈도우11 포맷하고 해보아도 같은증상이네요.

sysnet4admin commented 10 months ago

안녕하세요 문제가 확실히 정의 되었을 때 질문이 주시는 것을 부득이하게 요청드립니다.

 (X) 2대 이상 동일하게 문제가 발생함 ~ 2대이상에서 테스트해보지 못했습니다.

책을 집필한 이후 문제가 생기는 것을 follow up하기 위해 현재 issues 페이지는 운영되고 있습니다. 현재 발생하신 이슈가 정확하게 정의되지 않으면 답변하기 어려울 뿐만 아니라 제가 재현할 수 없는 부분에 대해서도 해결을 해드리기가 어렵습니다.

우선 3.1.3에는 nginx-pod.yaml이 존재하지 않고 3.1.6에 존재하는 nginx-pod.yaml을 배포하면 정상적으로 동작합니다.

[root@m-k8s ch3]# cd 3.1.6 
[root@m-k8s 3.1.6]# ls -rlt 
total 4
-rw-r--r--. 1 root root 115 Nov 15 09:42 nginx-pod.yaml
[root@m-k8s 3.1.6]# k apply -f nginx-pod.yaml 
pod/nginx-pod created
[root@m-k8s 3.1.6]# k get po -o wide 
NAME                          READY   STATUS    RESTARTS   AGE   IP               NODE     NOMINATED NODE   READINESS GATES
fs-echo-ip-5db6b4d665-7ghpv   1/1     Running   1          56d   172.16.103.130   w2-k8s   <none>           <none>
jenkins-76496d9db7-2f6rx      2/2     Running   2          56d   172.16.171.69    m-k8s    <none>           <none>
nginx-pod                     1/1     Running   0          24s   172.16.132.2     w3-k8s   <none>           <none>

해당 문제는 현재 사용하시는 호스트 및 환경에 어떤 제약(Network등) 또는 문제에서 기인하는 것으로 보입니다.

sysnet4admin commented 10 months ago

문제

현재 책에서 사용하고 있는 docker-ce(v18.09)에서는 문제가 발생하지 않으나, ch3의 docker(v1.13.1)에서는 문제가 재현 됨을 확인했습니다. 문제의 원인은 Docker의 'missing signature key' 이며,

Warning  Failed     2s (x2 over 19s)  kubelet, w2-k8s    Failed to pull image "nginx": rpc error: code = Unknown desc = missing signature key

upgrade하면 해결되긴 하나...이렇게 하는 경우 ch4로 넘어갈 때 연결성에 문제가 있어서 해결 방법에 대해서 고민 중에 있습니다. 우선

임시 해결 방법

ch4/4.3.4/k8s-SingleMaster-18.9_9_w_auto-compl 에 있는 Vagrantfile+연결파일 들로 진행하시면 해당 문제는 발생하지 않습니다.

조치 방법이 결정되면 다시 공지 드리도록 하겠습니다. 사용에 불편을 끼쳐드려서 죄송합니다.

ksnd0297 commented 10 months ago

저도 동일한 이슈를 겪고 있습니다. 1.13.1 에서 왜 missing signature key 에러가 발생하는지도 알려주시면 감사하겠습니다.

sysnet4admin commented 10 months ago

문제 원인

도커 1.13.1 버전에서 OCI(Open Container initiative) 형식이 다른(vnd.oci)컨테이너 이미지에 대해서 pulling이 되지 않음. 이 경우에 출력되는 메시지가 missing signature key 인 이유는 도커 1.13.1 버전에서 식별해야하는 매니페스트(MediaType) 형식과 nginx:latest(현재 1.25.3)의 매니페스트(MediaType)이 달라지면서 signatures를 더이상 제공하지 않아 해당 에러에 해당하는 코드가 반환되면서 컨테이너 이미지 pull 되지 않게 되었습니다.

var (
    // ErrInvalidSignContent is used when the content to be signed is invalid.
    ErrInvalidSignContent = errors.New("invalid sign content")

    // ErrInvalidJSONContent is used when invalid json is encountered.
    ErrInvalidJSONContent = errors.New("invalid json content")

    // ErrMissingSignatureKey is used when the specified signature key
    // does not exist in the JSON content.
    ErrMissingSignatureKey = errors.New("missing signature key") <<<<<
)
<중략>
// ParsePrettySignature parses a formatted signature into a
// JSON signature. If the signatures are missing the format information
// an error is thrown. The formatted signature must be created by
// the same method as format signature.
func ParsePrettySignature(content []byte, signatureKey string) (*JSONSignature, error) {
    var contentMap map[string]json.RawMessage
    err := json.Unmarshal(content, &contentMap)
    if err != nil {
        return nil, fmt.Errorf("error unmarshalling content: %s", err)
    }
    sigMessage, ok := contentMap[signatureKey]
    if !ok {
        return nil, ErrMissingSignatureKey
    }

문제의 세부 원인은 가장 하단의 문제 세부 원인 분석을 참고 하시기 바랍니다.

해결 방법

ch3/3.1.3에 있는 Vagrantfile을 이용해서 다시 vagrant up 진행 또는 새로 업로드된 가상 머신(VM) 이미지를 이용해서 실습을 진행

영향 받는 페이지

P89: config.sh 끝 부분에 docker-ce를 받기 위한 docker repo가 추가됨 P149: kubectl get nodes -o wide의 결괏값 중에 CONTAINER-RUNTIME이 바뀜 P255: 현재 사용하는 도커 버전이 18.06.0이라고 기입되어야 하고, 끝 부분에 CONTAINER-RUNTIME이 변경됨

변경 후 확인

노드 상태 확인

[root@m-k8s ~]# kubectl get nodes
NAME     STATUS   ROLES    AGE     VERSION
m-k8s    Ready    master   13m     v1.18.4
w1-k8s   Ready    <none>   9m27s   v1.18.4
w2-k8s   Ready    <none>   5m39s   v1.18.4
w3-k8s   Ready    <none>   115s    v1.18.4

디플로이먼트 배포 테스트

[root@m-k8s ~]# kubectl create deployment nginx --image=nginx 
deployment.apps/nginx created
[root@m-k8s ~]# kubectl scale deployment nginx --replicas 6
deployment.apps/nginx scaled
[root@m-k8s ~]# kubectl get pods -o wide 
NAME                    READY   STATUS    RESTARTS   AGE     IP               NODE     NOMINATED NODE   READINESS GATES
nginx-f89759699-6m9fw   1/1     Running   0          108s    172.16.221.130   w1-k8s   <none>           <none>
nginx-f89759699-9htz5   1/1     Running   0          108s    172.16.221.129   w1-k8s   <none>           <none>
nginx-f89759699-b4mwr   1/1     Running   0          108s    172.16.132.2     w3-k8s   <none>           <none>
nginx-f89759699-b8jhs   1/1     Running   0          108s    172.16.103.130   w2-k8s   <none>           <none>
nginx-f89759699-g5rzw   1/1     Running   0          108s    172.16.103.129   w2-k8s   <none>           <none>
nginx-f89759699-tb9gm   1/1     Running   0          2m25s   172.16.132.1     w3-k8s   <none>           <none>


문제 세부 원인 분석

컨테이너 이미지는 보통 다음 4가지로 구성되어 있습니다. [참고 자료]

이때 내려받은 최신(latest) nginx의 해석을 위해서 manifest의 mediatype을 구분합니다.
1.13.1 도커 버전에서 mediatype을 정상적으로 인지하기 위해서는 mediatype을 application/vnd.docker.distribution.manifest.list.v2+json 와 (vnd.docker가 중요) 같은 형태로 제공되어야 하나 최신 nginx 이미지는 'application/vnd.oci.image.manifest.v1+json' 으로 (vnd.oci가 중요) 제공됩니다. 이에 반해 예를 들면 최신 nginx 이미지가 아닌 1.18의 경우에는 application/vnd.docker.distribution.manifest.list.v2+json 형태로 제공됩니다.

1.18의 mediatype

[nginx](https://explore.ggcr.dev/?repo=nginx):[1.18](https://explore.ggcr.dev/?image=nginx:1.18&mt=application%2Fvnd.docker.distribution.manifest.list.v2%2Bjson)
Docker-Content-Digest: [sha256:e90ac5331fe095cea01b121a3627174b2e33e06e83720e9a934c7b8ccc9c55a0](https://explore.ggcr.dev/?image=nginx@sha256:e90ac5331fe095cea01b121a3627174b2e33e06e83720e9a934c7b8ccc9c55a0&mt=application%2Fvnd.docker.distribution.manifest.list.v2%2Bjson&size=1862)
Content-Length: 1862
Content-Type: [application/vnd.docker.distribution.manifest.list.v2+json](https://explore.ggcr.dev/https://github.com/opencontainers/image-spec/blob/main/image-index.md)
[crane](https://github.com/google/go-containerregistry/blob/main/cmd/crane/README.md) [manifest](https://github.com/google/go-containerregistry/blob/main/cmd/crane/doc/crane_manifest.md) nginx:1.18 | jq .
{
"schemaVersion": 2,
"mediaType": ["application/vnd.docker.distribution.manifest.list.v2+json"](https://github.com/opencontainers/image-spec/blob/main/image-index.md),
<생략>

latest(1.25.3)의 mediatype

[nginx](https://explore.ggcr.dev/?repo=nginx):[latest](https://explore.ggcr.dev/?image=nginx:latest&mt=application%2Fvnd.oci.image.index.v1%2Bjson)
Docker-Content-Digest: [sha256:4c0fdaa8b6341bfdeca5f18f7837462c80cff90527ee35ef185571e1c327beac](https://explore.ggcr.dev/?image=nginx@sha256:4c0fdaa8b6341bfdeca5f18f7837462c80cff90527ee35ef185571e1c327beac&mt=application%2Fvnd.oci.image.index.v1%2Bjson&size=7588)
Content-Length: 7588
Content-Type: [application/vnd.oci.image.index.v1+json](https://explore.ggcr.dev/https://github.com/opencontainers/image-spec/blob/main/image-index.md)
[crane](https://github.com/google/go-containerregistry/blob/main/cmd/crane/README.md) [manifest](https://github.com/google/go-containerregistry/blob/main/cmd/crane/doc/crane_manifest.md) nginx:latest | jq .
{
"schemaVersion": 2,
"mediaType": ["application/vnd.oci.image.index.v1+json"](https://github.com/opencontainers/image-spec/blob/main/image-index.md),
"manifests": [
{
"mediaType": ["application/vnd.oci.image.manifest.v1+json"](https://github.com/opencontainers/image-spec/blob/main/manifest.md),
<생략>

이렇게 구분한 이후에 vnd.docker의 경우 signatures를 확인하는데, vnd.oci에서는 signatures를 제공하지 않기 때문에 해당 missing signatures key에러가 발생하고, 이미지 pulling이 진행되지 않는 것입니다.
Note: explore.ggcr.dev를 통해서는 signatures 정보가 확인되지 않습니다. 해당 정보를 확인하기 위해서는 다음의 과정이 필요합니다.

 # REST API 접속을 위한 정보 설정
REGISTRY=https://index.docker.io/v2
REPO=library
IMAGE=nginx
TOKEN=$(curl -sSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$REPO/$IMAGE:pull" | jq --raw-output .token)

# nginx:1.18의 manifest 에서 signature 확인
TAG=1.18.0; curl -LH "Authorization: Bearer ${TOKEN}" "$REGISTRY/$REPO/$IMAGE/manifests/$TAG" | grep -A100 "signature"

 "signatures": [
      {
         "header": {
            "jwk": {
               "crv": "P-256",
               "kid": "WOWS:W6D3:6V6P:OFFX:6Q5M:JDAN:JGJB:ZEZC:4IFX:BSRX:LNNJ:3SO6",
100 12738  100 12738    0     0  12657      0  0:00:01  0:00:01 --:--:-- 12662
               "kty": "EC",
               "x": "5oKSYt2ZVMjgo74AsU1pHRRrepiziRDmkSE8PFBymw0",
               "y": "uHs6c2nGEu9UKSZFrFitU3IOihPd54d57TvuINww8EQ"
            },
            "alg": "ES256"
         },
         "signature": "oNticNtGCIRyZvfjL7nc7UQSNV9sE_y04QKNP0J3aR4vQl2eeYfpFBopp96o_ATHqjPz-Fv_QWeLDdZas_578Q",
         "protected": "eyJmb3JtYXRMZW5ndGgiOjEyMDkwLCJmb3JtYXRUYWlsIjoiQ24wIiwidGltZSI6IjIwMjQtMDEtMTRUMDQ6NDY6NDhaIn0"
      }
   ]
}

앞으로 나올 컨테이너 이미지들이 계속 docker.vnd를 지원하지 않을 것으로 예상되고, oci.vnd를 지원해야 하는 상황에서 테스트 해 본 결과 가장 변경 점이 적은 버전은 도커 18.06.0으로 확인되었습니다. 따라서 ch3/3.1.3에 도커 버전을 1.13.1 에서 18.06.0으로 변경해서 해당 문제를 조치하였습니다.

참고 사항

nginx 최신(latest) 과 1.18을 비교

nginx 최신(latest) 과 1.18을 비교하고 싶으시다면 다음을 클릭해서 확인해 보실 수 있습니다.

OCI 표준 관련

OCI 에서 상호 호환을 위해서 application/vnd.oci.image.manifest.v1+json 을 포함하도록 권장합니다.

현재 이슈는 1주일간 모니터링 된 후에 Close 됩니다. 감사합니다. 조 훈, 심근우, 문성주 드림