1.4.1.1 OCIR 이미지 사용하기
Oracle Cloud Infrastructure Registry(OCIR)는 오라클이 제공하는 관리형 컨테이너 레지스트리로 Docker V2 API를 지원하며, Open Container Initiate 호환 컨테이너 레지스트리입니다. docker cli를 통해 이미지를 Push, Pull 해서 사용할 수 있으며, Kubernetes 클러스터에서도 사용할 수 있습니다.
OCIR에 이미지를 사용하기 위해서는 먼저 등록 작업이 필요하며, 앞서 예제에서 사용한 nginx 이미지를 아래 절차에 따라 등록해 봅니다.
OCIR Repository 만들기
-
OCI 콘솔에 로그인합니다.
-
좌측 상단 햄버거 메뉴에서 Developer Services > Containers & Artifacts > Container Registry로 이동합니다.
-
List Scope에서 대상 Compartment를 선택합니다.
-
이미지를 Push하기 전에 먼저 OCIR에 repository를 생성이 필요합니다.
Create repository를 클릭하여 아래와 같이 nginx repository를 생성합니다. Push, Pull 모두 인증 테스트를 위해 Access 모드를 Private으로 선택합니다.
-
생성 완료
-
Repository 화면에서 Namespace를 복사해 둡니다.
OCI Auth Token 만들기
docker cli로 docker hub에 이미지를 등록하거나, 가져올때 username/password로 docker login을 통해 로그인을 합니다. OCIR에도 마찬가지로 로그인이 필요하며, password 대신 보안을 위해 Auth Token을 사용합니다.
-
우측 상단 사용자의 Profile 아이콘을 클릭하여 My profile로 이동합니다.
- 아래 그림상의 유저의 username은 Identity Domain 이름인 Default를 제외한 kildong@example.com입니다.
-
왼쪽 아래 Resources > Auth Token으로 이동합니다.
-
Auth Token 생성을 위해 Generate Token을 클릭합니다.
-
설명을 입력하고 생성합니다. Auth Token은 생성시에만 볼수 있으므로 복사해 둡니다.
OCIR 로그인 및 이미지 Push
-
앞서 생성한 Auth Token을 통해 Cloud Shell 또는 접속 환경에서 docker cli로 로그인 합니다.
- OCIR 주소:
<region-key>.ocir.io
- region-key: 예, yny
- region-identifier: 예, ap-chuncheon-1
- 전체 Region별 OCIR 주소: Availability by Region
- Username:
<tenancy-namespace>/<username>
형식- Username: OCI 콘솔에서 유저 Profile에서 보이는 유저명을 사용합니다.
<tenancy-namespace>/<username>
- tenancy-namespace: 앞서 Repository 생성시 확인한 tenancy-namespace 또는 Cloud Shell에서
oci os ns get
으로 확인 가능
- Password: 앞서 생성한 로그인할 유저의 Auth Token
kildong@cloudshell:~ (ap-chuncheon-1)$ oci os ns get { "data": "cnxxxxxxxxgq" } kildong@cloudshell:~ (ap-chuncheon-1)$ docker login yny.ocir.io Username: cnxxxxxxxxgq/kildong@example.com Password: WARNING! Your password will be stored unencrypted in /home/kildong/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
- OCIR 주소:
-
이미지 Push
- OCIR에 생성한 Repository로 Push 하기 위해 아래 형식으로 태그를 한 후 Push 하면 됩니다.
<region-key>.ocir.io/<tenancy-namespace>/<repo-name>:<tag>
- nginx:latest 예시
docker pull nginx:latest docker tag nginx:latest yny.ocir.io/cnxxxxxxxxgq/nginx:latest docker push yny.ocir.io/cnxxxxxxxxgq/nginx:latest
- OCIR에 생성한 Repository로 Push 하기 위해 아래 형식으로 태그를 한 후 Push 하면 됩니다.
-
OCIR 확인
OCI 서비스 콘솔로 다시 돌아가서 대상 Compartment 기준으로 Push한 이미지가 정상적으로 등록된 것을 알 수 있습니다.
실수를 막기 위한 참고 사항
다음과 같은 상황에서는 docker push하면 어떻게 될까요?
-
Push 전에 OCIR Repository를 사전에 만들지 않은 경우
=> 사전에 OCIR Repository를 만들지 않으면, 기본 설정에 의해 root compartment 쪽에 push 됩니다.
-
dev/nginx:latest(또는 bitnami/nginx:latest)와 같이 이미지 이름 앞에 추가 적인 경로가 있는 경우에 OCIR Repository를 dev 로만 만든 경우
=> dev/nginx 까지를 Repository 이름으로 생각합니다. 그래서 OCIR에서 dev/nginx를 Repository Name으로 입력하여 생성합니다. 그렇게 만들지 않는 경우 동일하게 root compartment 쪽에 push 됩니다.
Container Registry 우측 상단에 Settings를 클릭하여 설정정보를 보면 아래와 같이 대상 repository가 없는 경우 root compartment에 private repository를 자동으로 새로 만들고 push 하는 것이 기본 값으로 체크되어 있습니다.
OCIR 이미지로 OKE 클러스터에 배포
OCIR 이미지 배포 테스트
-
가장 흔한 형태인 Public Container Registry에 이미지를 가져와서 OKE 클러스터에 배포를 해봅니다.
kubectl create deployment nginx-ocir --image=yny.ocir.io/cnxxxxxxxxgq/nginx:latest
-
배포 결과 아래와 같이 private repository로 인증문제로 이미지를 가져오는 오류가 발생한 것을 알수 있습니다.
kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl create deployment nginx-ocir --image=yny.ocir.io/cnxxxxxxxxgq/nginx:latest deployment.apps/nginx-ocir created kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl get pod NAME READY STATUS RESTARTS AGE nginx-ocir-56d7b8d55c-t667j 0/1 ImagePullBackOff 0 15s kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl describe pod nginx-ocir-56d7b8d55c-t667j Name: nginx-ocir-56d7b8d55c-t667j ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- ... Warning Failed 15s (x2 over 27s) kubelet Failed to pull image "yny.ocir.io/cnxxxxxxxxgq/nginx:latest": rpc error: code = Unknown desc = reading manifest latest in yny.ocir.io/cnxxxxxxxxgq/nginx: denied: Anonymous users are only allowed read access on public repos Warning Failed 15s (x2 over 27s) kubelet Error: ErrImagePull Normal BackOff 1s (x2 over 26s) kubelet Back-off pulling image "yny.ocir.io/cnxxxxxxxxgq/nginx:latest" Warning Failed 1s (x2 over 26s) kubelet Error: ImagePullBackOff
OCIR Private Repository 이미지 배포 테스트 - imagepullsecret
Private Repository에서 이미지를 가져와서 사용하려면 인증을 위한 secret을 등록해서 사용해야 합니다. 아래 절차에 따라 secret을 만들어 사용합니다.
-
앞서 Auth Token을 사용하여 docker login을 하였습니다. 사용자 홈 밑에 .docker/config.json에 인증정보가 저장됩니다.
kildong@cloudshell:~ (ap-chuncheon-1)$ docker login yny.ocir.io Username: cnxxxxxxxxgq/kildong@example.com Password: WARNING! Your password will be stored unencrypted in /home/kildong/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
-
위 인증 정보를 통해 secret을 만듭니다.
kubectl create secret generic ocir-secret \ --from-file=.dockerconfigjson=$HOME/.docker/config.json \ --type=kubernetes.io/dockerconfigjson
-
또는 docker login 정보 없이 직접 secret을 만들 수도 있습니다.
kubectl create secret docker-registry <secret-name> --docker-server=<region-key>.ocir.io --docker-username='<tenancy-namespace>/<oci-username>' --docker-password='<oci-auth-token>' --docker-email='<email-address>'
-
아래와 같이 imagepullsecret을 사용하여 다시 배포합니다.
apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx-ocir name: nginx-ocir spec: replicas: 1 selector: matchLabels: app: nginx-ocir template: metadata: labels: app: nginx-ocir spec: containers: - name: nginx image: yny.ocir.io/cnxxxxxxxxgq/nginx:latest imagePullSecrets: - name: ocir-secret
-
아래와 같이 Running 상태로 정상 배포되는 것을 볼 수 있습니다.
kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl create secret generic ocir-secret \ > --from-file=.dockerconfigjson=$HOME/.docker/config.json \ > --type=kubernetes.io/dockerconfigjson secret/ocir-secret created kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl get secret NAME TYPE DATA AGE ocir-secret kubernetes.io/dockerconfigjson 1 46s kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl apply -f nginx-ocir-deployment.yaml deployment.apps/nginx-ocir configured kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl get all NAME READY STATUS RESTARTS AGE pod/nginx-ocir-86bcf7867c-tk4m5 1/1 Running 0 86s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP,12250/TCP 152m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-ocir 1/1 1 1 7m21s NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-ocir-86bcf7867c 1 1 1 87s
OCIR Private Repository 이미지 배포 테스트 - default imagepullsecret
매번 imagepullsecret을 지정하는 것이 불편한 경우 기본으로 사용할 Container Repository에 대한 인증을 default로 저장하여 사용할 수도 있습니다.
-
namespace에 default serviceaccount가 있는데, 여기에 아래와 같이 imagepullsecret을 추가합니다.
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "ocir-secret"}]}'
-
그 결과 아래와 같이 default serviceaccount에 기본적으로 사용할 imagesecret이 추가되었습니다
kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "ocir-secret"}]}' serviceaccount/default patched kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl get sa default -o yaml apiVersion: v1 imagePullSecrets: - name: ocir-secret kind: ServiceAccount metadata: creationTimestamp: "2023-05-16T07:52:12Z" name: default namespace: default resourceVersion: "37675" uid: 477e180e-82af-4ff4-a1cd-b9bd12763078
-
앞서 배포한 yaml을 삭제하고 인증정보가 없어 처음 실패한 명령으로 다시 배포합니다.
kubectl delete deployment nginx-ocir kubectl create deployment nginx-ocir --image=yny.ocir.io/cnxxxxxxxxgq/nginx:latest
-
결과확인하면 default imagepullsecret을 사용하여 정상 배포됨을 알 수 있습니다.
kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl delete deployment nginx-ocir deployment.apps "nginx-ocir" deleted kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl create deployment nginx-ocir --image=yny.ocir.io/cnxxxxxxxxgq/nginx:latest deployment.apps/nginx-ocir created kildong@cloudshell:~ (ap-chuncheon-1)$ kubectl get all NAME READY STATUS RESTARTS AGE pod/nginx-ocir-56d7b8d55c-65d22 1/1 Running 0 12s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP,12250/TCP 156m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-ocir 1/1 1 1 12s NAME DESIRED CURRENT READY AGE replicaset.apps/nginx-ocir-56d7b8d55c 1 1 1 13s
이 글은 개인으로서, 개인의 시간을 할애하여 작성된 글입니다. 글의 내용에 오류가 있을 수 있으며, 글 속의 의견은 개인적인 의견입니다.