-
[Kubernetes] private docker registry Pod 설치인프라/Kubernetes 2020. 12. 2. 10:32
Docker Registry
# vi docker-registry.yaml apiVersion: v1 kind: Pod metadata: name: docker-registry namespace: infra labels: app: docker-registry #label spec: #nodeName: kube-node2 #node를 지정해도되고 안해도됨 #nodeSelector: // node labels를 지정해도 됨 #kubernetes.io/hostname: kube-node2 containers: - name: docker-registry image: registry:2.7.1 ports: - containerPort: 5000 #registry 기본 port volumeMounts: - mountPath: /var/lib/registry #container directory name: host-path #아래에 volumes name volumes: #host pc volume생성 - name: host-path hostPath: path: /docker-registry type: DirectoryOrCreate --- apiVersion: v1 kind: Service metadata: name: docker-registry namespace: infra spec: type: NodePort selector: app: docker-registry ports: - protocol: TCP port: 5000 targetPort: 5000 nodePort: 30500
registry를 kubernetes Pod로 띄우고 외부에서 30500포트로 접근하기위해 yaml을 작성해준다. (1개의 Pdo만 띄우기 위해서 Deployment를 통해 생성하지 않았다.)
spec.containers.image: registry:2.7.1 은 docker-hub에 있는 official registry container 이다.
Pod가 생성될 Node에 volumeMounts를 설정했는데 registry 기본 config.yml을 보면
version: 0.1 log: fields: service: registry storage: cache: blobdescriptor: inmemory filesystem: rootdirectory: /var/lib/registry http: addr: :5000 headers: X-Content-Type-Options: [nosniff] health: storagedriver: enabled: true interval: 10s threshold: 3
storage.filesystem.rootdirectory의 경로에 images들이 저장된다.
# kubectl get pods -n infra -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES docker-registry 1/1 Running 1 136m 172.16.0.107 kube-node2 <none> <none>
생성된 Node를 찾아가 보면 volume hostPath type DirectoryOrCreate 로 인해서 자동생성된 directory를 볼 수 있다.
# ls -l / | grep docker-registry drwxr-xr-x. 3 root root 20 12월 1 14:26 docker-registry
생성할 수 있는 자세한 volume 유형은 여기를 참조
{hostip}:30500 로 api를 날려서 정상 실행여부를 확인해보자
curl -v 192.168.5.1:30500/v2 * About to connect() to 192.168.5.1 port 30500 (#0) * Trying 192.168.5.1... * Connected to 192.168.5.1 (192.168.5.1) port 30500 (#0) > GET /v2 HTTP/1.1 > User-Agent: curl/7.29.0 > Host: 192.168.5.1:30500 > Accept: */* > < HTTP/1.1 301 Moved Permanently < Content-Type: text/html; charset=utf-8 < Docker-Distribution-Api-Version: registry/2.0 < Location: /v2/ < Date: Tue, 01 Dec 2020 08:00:49 GMT < Content-Length: 39 < <a href="/v2/">Moved Permanently</a>. * Connection #0 to host 192.168.5.1 left intact
이렇게 나온다면 정상적으로 registry가 떠있다는 것이다.
그럼 이제 image를 push해보자.
# vi Dockerfile FROM ubuntu:12.04 RUN mkdir /test
테스트용으로 ubuntu에 /test 디렉로리만 생성한 image를 생성해보자
# docker build -t 192.168.5.1:30500/test:v1.0 . Sending build context to Docker daemon 4.608kB Step 1/2 : FROM ubuntu:12.04 ---> 5b117edd0b76 Step 2/2 : RUN mkdir /test ---> Running in 2ad98801e2c4 Removing intermediate container 2ad98801e2c4 ---> b924a4ba8074 Successfully built b924a4ba8074 Successfully tagged 192.168.5.1:30500/test:v1.0
-t 옵션으로 REPOSITORY경로와 ImageName:Tag로 Dockerfile을 build하자
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.5.1:30500/test v1.0 b924a4ba8074 50 seconds ago 104MB
제대로 생성된것을 확인하고 push를 해보자
# docker push 192.168.5.1:30500/test:v1.0 The push refers to repository [192.168.5.1:30500/test] Get https://192.168.5.1:30500/v2/: http: server gave HTTP response to HTTPS client
server gave HTTP response to HTTPS client라는 오류가 뜨면서 실패한다.
이는 docker push나 pull이 https로 동작하기 때문인데, 우리가 설치한 registry가 http로만 현재 동작하고 있기 때문이라고 한다. 그래서 push나, pull을 할 때 보안이 적용되지 않도록 insecure 설정을 해주어야한다.
[Kubernetes] 쿠버네티스 설치하기 (1) - Container runtimes 를 통해 docker를 설치하였다면 /etc/docker/daemon.json 를 통해 dockerd의 설정을 하였을 것이다. 이부분야 insecure 설정을 추가해주자.
# vi /etc/docker/daemon.json { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ], "insecure-registries" : ["docker-registry.com:30500"] }
ip로 설정하지않고 domain name (docker-registry.com) 으로 설정해 놓았다. /etc/hosts파일에 설정해놓고 사용하면 ip가 바뀌어도 아무런 영향이 없기 때문에 위와같이 설정하겠다.
"insecure-registries" 설정을 통해 docker 에서 우리가 만든 private docker registry의 ip:port로의 통신은 보안을 무시하게 해준다. (docs.docker.com/registry/insecure/)를 살펴보면
- If HTTPS is available but the certificate is invalid, ignore the error about the certificate.
- If HTTPS is not available, fall back to HTTP.
증명서 무시, https가 불가능하면 http로 변경해서 보내게 해준다고 한다.
# vi /etc/hosts 192.168.5.1 docker-registry.com
위와같이 hosts 파일에 본인의 host ip를 설정해주자. 그리고 restart!
systemctl restart docker
# docker rmi 192.168.5.1:30500/test:v1.0 Untagged: 192.168.5.1:30500/test:v1.0 Deleted: sha256:b924a4ba807463d9301c2bf30ccb65d3032e7aa03ce751efe765b02a820dc039 Deleted: sha256:8aca5f5c3a1ec66b0b06ab11b2b33847edc180d125407053391edf8aec6f0b35
ip로 설정되어있던 image를 삭제 후
# docker build -t docker-registry.com:30500/test:v1.0 . Sending build context to Docker daemon 4.608kB Step 1/2 : FROM ubuntu:12.04 ---> 5b117edd0b76 Step 2/2 : RUN mkdir /test ---> Running in 2f706b4beb8d Removing intermediate container 2f706b4beb8d ---> 00c57a0e17c4 Successfully built 00c57a0e17c4 Successfully tagged docker-registry.com:30500/test:v1.0
domain name을 사용하여 새로 만들어주자.
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker-registry.com:30500/test v1.0 00c57a0e17c4 29 seconds ago 104MB
# docker push docker-registry.com:30500/test:v1.0
그리고 다시한번 push를 실행해보자! ip를 domain name으로 변경하였다.
# docker push docker-registry.com:30500/test:v1.0 The push refers to repository [docker-registry.com:30500/test] 4756cb421d70: Pushed 3efd1f7c01f6: Layer already exists 73b4683e66e8: Layer already exists ee60293db08f: Layer already exists 9dc188d975fd: Layer already exists 58bcc73dcf40: Layer already exists v1.0: digest: sha256:18dfa93ff7781705b7a917ba9d5ae0d2972a181b7fcb0c2f827d15e1cd71fb91 size: 1566
pushed가 성공하였다! (Layer already exists는 이전에 같은걸 넣어놔서 뜬것이므로 무시해도 된다)
# curl docker-registry.com:30500/v2/_catalog {"repositories":["test"]}
curl을 통해 등록된 repositories를 확인해보면 정상적으로 들어가 있는것을 확인할 수 있다.
# curl docker-registry.com:30500/v2/test/tags/list {"name":"test","tags":["v1.0"]}
test image의 tags도 확인
# kubectl exec docker-registry -n infra -- ls -l /var/lib/registry/docker/registry/v2/repositories/test/_manifests/tags/ total 0 drwxr-xr-x 4 root root 34 Dec 1 07:06 v1.0
이렇게 실제 Pod 안에 reposoitories 를 살펴봐도 test가 생성되어 있는것을 확인할 수 있다.
# ll /docker-registry/docker/registry/v2/repositories/test/_manifests/tags/ 합계 0 drwxr-xr-x. 4 root root 34 12월 1 16:06 v1.0
volumeMount 했던 Node에서도 생성되어 있는것을 확인할 수 있다.
Pod 내부에 application을 확인해보니 시간이 안맞다 ... 이 부분도 나중에 확인해야할 듯 싶다.
# docker rmi docker-registry.com:30500/test:v1.0 Untagged: docker-registry.com:30500/test:v1.0 Untagged: docker-registry.com:30500/test@sha256:18dfa93ff7781705b7a917ba9d5ae0d2972a181b7fcb0c2f827d15e1cd71fb91 Deleted: sha256:00c57a0e17c409690e0073e6a033935fce8fb04e8b680b80a78c03fa04bbb5fd Deleted: sha256:3b290c2dffe58dd36be164bf08a5940285405daf2f4bc994857e47b65ba6d0b2
지우고 다시 pull도 받아보자
# docker pull docker-registry.com:30500/test:v1.0 v1.0: Pulling from test 396e9d6ee8c9: Already exists 403b0fc2e6f1: Already exists 7124ef1a91d2: Already exists f47441d15565: Already exists 588e8920e707: Already exists 6dbaa51c9a68: Pull complete Digest: sha256:18dfa93ff7781705b7a917ba9d5ae0d2972a181b7fcb0c2f827d15e1cd71fb91 Status: Downloaded newer image for docker-registry.com:30500/test:v1.0 docker-registry.com:30500/test:v1.0
# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker-registry.com:30500/test v1.0 00c57a0e17c4 22 minutes ago 104MB
잘 동작한다.
자 push를 통해서 image를 생성하였으니 이젠 해당 image를 Pod로 띄워보자!
# vi test.yaml apiVersion: v1 kind: Pod metadata: name: test labels: app: test #label spec: nodeName: kube-node2 containers: - name: test image: docker-registry.com:30500/test:v1.0 ports: - containerPort: 80 command: ["/bin/sh"] args: ["-c", "while true; do echo hello; sleep 5;done"]
test로 띄울 Pod yaml을 생성 nodeName으로 난 특정 Node에 띄우도록 하였다.
그리고 image가 아무것도 실행하고 있지않아 container가 바로 종료하는것을 방지하기위해 command, args를 이용하여 shellscript를 실행하였다.
# kubectl apply -f test.yaml pod/test created
# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test 0/1 ImagePullBackOff 0 83s 172.16.0.109 kube-node2 <none> <none>
그러나 위와같이 ImagePullBackOff 상태가 되면서 실패할 것이다!
# kubectl describe pods/test . . . Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Pulling 12s (x3 over 53s) kubelet Pulling image "docker-registry.com:30500/test:v1.0" Warning Failed 12s (x3 over 53s) kubelet Failed to pull image "docker-registry.com:30500/test:v1.0": rpc error: code = Unknown desc = Error response from daemon: Get https://docker-registry.com:30500/v2/: dial tcp: lookup docker-registry.com on 192.168.5.254:53: no such host Warning Failed 12s (x3 over 53s) kubelet Error: ErrImagePull Normal BackOff 1s (x4 over 53s) kubelet Back-off pulling image "docker-registry.com:30500/test:v1.0" Warning Failed 1s (x4 over 53s) kubelet Error: ImagePullBackOff
docker-registry.com을 찾지못해서 pull에 실패하였다.
해당 node에도 /etc/hosts에 docker-registry.com을 추가하여주자.
# kubectl delete -f test.yaml pod "test" deleted
# kubectl apply -f test.yaml pod/test created
삭제했다가 다시 생성
# kubectl describe pods/test Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Pulling 14s kubelet Pulling image "docker-registry.com:30500/test:v1.0" Warning Failed 14s kubelet Failed to pull image "docker-registry.com:30500/test:v1.0": rpc error: code = Unknown desc = Error response from daemon: Get https://docker-registry.com:30500/v2/: http: server gave HTTP response to HTTPS client Warning Failed 14s kubelet Error: ErrImagePull Normal SandboxChanged 13s kubelet Pod sandbox changed, it will be killed and re-created. Normal BackOff 11s (x3 over 12s) kubelet Back-off pulling image "docker-registry.com:30500/test:v1.0" Warning Failed 11s (x3 over 12s) kubelet Error: ImagePullBackOff
docker-registry.com은 찾았으나, 여전히 실패할 것이다.
위에서 docker push 했을 때와 같은 오류가 발생할 것이다.
이는 해당 Node의 docker를 이용해서 pull을 받는 것이기 때문에 Node에 daemon.json 설정에도 insecure을 설정해 주어야한다. /etc/docker/daemon.json에 위처럼 insecure를 추가후 docker를 재시작 해주자!
그리고 다시 생성하면 그제서야 정상적으로 생성이된다!
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Pulled 11s kubelet Container image "docker-registry.com:30500/test:v1.0" already present on machine Normal Created 11s kubelet Created container test Normal Started 11s kubelet Started container test
# kubectl get pods/test -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test 1/1 Running 0 6m33s 172.16.0.115 kube-node2 <none> <none>
# kubectl exec test -- ls / | grep test test
container내부에 /test 디렉토리가 있는것도 확인
[root@kube-node2 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 970114cc25e3 00c57a0e17c4 "/bin/sh -c 'while t…" 7 minutes ago Up 7 minutes k8s_test_test_default_8e825cfd-a8c3-4438-ad3d-8659d42065b5_0 ed0c2fd23ad2 k8s.gcr.io/pause:3.2 "/pause" 7 minutes ago Up 7 minutes k8s_POD_test_default_8e825cfd-a8c3-4438-ad3d-8659d42065b5_0
실제 생성된 kube-node2에도 확인
마지막으로 docker registry pod를 삭제했다가 다시 생성해도 volume설정이 제대로 동작하는지 보자
# kubectl delete -f docker-registry.yaml pod "docker-registry" deleted service "docker-registry" deleted
# kubectl get pods -n infra No resources found in infra namespace.
# kubectl apply -f docker-registry.yaml pod/docker-registry created service/docker-registry created
# kubectl get pods -n infra NAME READY STATUS RESTARTS AGE docker-registry 1/1 Running 0 105s
# curl docker-registry.com:30500/v2/_catalog {"repositories":["test"]}
확인 완료!
앞으로 진행될 image들은 모두 private docker registry를 이용하여 저장하면 될 것 같다.
그리고 모든 Node의 docker daemon.json 설정파일에 insecure-registries 설정을 전부 해주도록 하자
'인프라 > Kubernetes' 카테고리의 다른 글
[Kubernetes] SVN Pod 생성 (0) 2020.12.07 [Kubernetes] Jenkins Pod 설치 (0) 2020.12.02 [Kubernetes] Visual하게 DashBoard를 설치, 접속해보자 (2) 2020.11.26 [Kubernetes] 설치 명령어 모음 (0) 2020.11.26 [Kubernetes] Horizontal Pod Autoscaler (0) 2020.11.25