Skip to content

Latest commit

 

History

History
680 lines (549 loc) · 22.4 KB

5. Quay.md

File metadata and controls

680 lines (549 loc) · 22.4 KB

5. Quay Install

목적

Quay는 기업 환경을 위한 분산 고가용성 컨테이너 이미지 레지스트리이다. On-Premises, Public Cloud 등 모든 컨테이너 환경 혹은 오케스트레이션 환경에서 작동가능한 것이 장점이다. Quay는 git과 통합되어 빌드 자동화 진행, 보안성, 접근 제어, 컨텐츠 분산, 확장가능한 API와 대규모 스케일의 Test 등의 특징을 갖는다. 본 프로젝트에서는 앞서 구축한 openshift와 함께 CI/CD Pipeline을 구현하기 위해 Quay를 설치한다.

전체 Architecture

1. 논리적 Architecture

  • Quay는 Openshift Container Platform의 외부 Node로써 구현
  • Quay가 외부 Source Registry로부터 Image를 받아와 Mirroring한 뒤에 Clair을 통해 CVE Metadata를 Fetch하고 Image 취약점을 검사
  • 본 프로젝트에서는 전체 리소스를 고려하여 Quay를 1중화로 진행

2. 물리적 Architecture(Quay Node 내부 컨테이너들간의 관계)

  • Quay : Container Registry로서 Quay Container를 Pod의 여러 구성 요소로 구성된 서비스로 실행
  • Database(Mysql) : Quay에서 기본 Metadata Storage로 사용
  • Redis(Key, Value Store) : Live Builder Log 및 Red Hat Quay turorial 저장
  • Clair : 컨테이너 이미지의 취약점을 검사하고 수정 사항을 제안
  • gitLab : 형상 관리 도구
  • Object Storage : 오브젝트 형태의 데이터를 저장할 수 있는 스토리지로 본 프로젝트는 On-premises 환경이므로 Minio 사용



Quay 설치 준비

설치 환경

  • quay : 3.2.1 v
  • quay-builder : 3.2.1 v
  • clair-jwt : 3.2.1 v
  • External IP : 192.168.100.10/24 (NAT)
  • Internal IP : 10.10.10.21
  • 방화벽 해제

Quay의 Port Forwarding

  • QuayBuilder : 80 Port
  • Redis : 6379 Port
  • MySQL : 3306 Port
  • QuayConfig : 28443 Port
  • Minio : 9000 Port
  • Gitlab : 18443, 18080, 18022 Port

Clair의 Port Forwarding

  • JWTproxy : 6060 Port
  • pgsql : 5432 Port
  • Postgresql : pgsql과 Link 연결



1. Quay 설치 사전 준비

  • Quay로 사용할 RHEL 7.8 OS의 가상머신을 생성한 뒤, 아래 과정 진행

  • RAM : 8 GB , vCPU : 3 Core , Disk : 60 GB

  • hostname 설정

    # Quay Node의 Hostname 변경
    hostnamectl set-hostname quay.redhat2.cccr.local
    
    # Quay Node와 Host PC에 각각 ip 추가
    # 해당 IP로 웹 콘솔 접근 가능 
    vi /etc/hosts
    192.168.100.10	quay.redhat2.cccr.local
    192.168.100.10	clair.redhat2.cccr.local
    192.168.100.10	gitlab.redhat2.cccr.local
  • RHEL OS 사용을 위해 Redhat 계정으로 Subscription을 등록

  • Subscription 등록 과정에서 Repository 활성화

    rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
    
    subscription-manager register # RedHat 계정 입력 
    Username: ${USERNAME}
    Password: ${PASSWORD}
    
    The system has been registered with ID: ~~~~
    The registered system name is: quay.redhat2.cccr.local
    
    subscription-manager list --available --matches '*RHEL*'
    subscription-manager attach --pool=<<Pool_ID>>
    subscription-manager repos --disable="*"
    subscription-manager repos --enable="rhel-7-server-rpms" --enable="rhel-7-server-extras-rpms"
    
    yum update -y
    # 업데이트 후, Server Reboot 
    reboot

2. Docker 설치

  • Docker 설치

    yum install docker device-mapper-libs device-mapper-event-libs**
    systemctl enable docker
    systemctl start docker
    systemctl is-active docker
  • Insecure Docker Registry 세팅

    vi /etc/sysconfig/docker
    ...
    # 내용 추가 
    ADD_REGISTRY=--add-registry '<<quay FQDN>>'
    INSECURE_REGISTRY=--insecure-registry '<<quay FQDN>>'

3. Quay 인증

  • quay.io에서 Red Hat Quay V3 Container Image을 얻기 위하여 Key를 통해 인증

    [root@quay ~]docker login -u="<<ID>>" -p="<<PASSWORD>>" quay.io



Quay 설치 과정

1. Database

  • Database 설치 디렉터리 생성

    mkdir -p /var/lib/mysql
    chmod -R 777 /var/lib/mysql
  • 환경변수 설정

    export MYSQL_CONTAINER_NAME=mysql
    export MYSQL_DATABASE=quay
    export MYSQL_PASSWORD=quay
    export MYSQL_USER=quay
    export MYSQL_ROOT_PASSWORD=quay
  • Quay의 Database는 PostgreSQL나 MySQL 모두 사용 가능

  • 본 프로젝트에서는 MySQL을 설치

    docker run --detach --restart=always \
    --env MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
    --env MYSQL_USER=${MYSQL_USER} \
    --env MYSQL_PASSWORD=${MYSQL_PASSWORD} \
    --env MYSQL_DATABASE=${MYSQL_DATABASE} \
    --name ${MYSQL_CONTAINER_NAME} \
    --publish 3306:3306 -v /var/lib/mysql:/var/lib/mysql/data:Z \
    registry.access.redhat.com/rhscl/mysql-57-rhel7
  • mysql 접근 가능한지 확인

    yum install -y mariadb
    
    mysql -h 192.168.100.10 -u root --password=quay
    
    Welcome to the MariaDB monitor.
    Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 5.7.24 MySQL Community Server (GPL)
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    Type 'help;' or '\h' for help. Type '\c' to clear the current input
    statement.
    MySQL [(none)]> \q
    Bye

2. Redis

  • Redis 설치 디렉토리 생성

    mkdir -p /var/lib/redis
    chmod -R 777 /var/lib/redis
  • Redis 설치

    docker run -d --restart=always -p 6379:6379 \
    --privileged=true -v /var/lib/redis:/var/lib/redis/data:Z \
    registry.access.redhat.com/rhscl/redis-32-rhel7
  • Redis와 통신 가능한지 확인

    yum install telnet -y
    
    telnet 192.168.100.10 6379
    
    [root@quay ~]# telnet 192.168.100.10 6379
    ..
    ..
    Escape character is '^]'.
    MONITOR
    +OK
    QUIT
    +OK
    Connection closed by foreign host.

3. Gitlab

  • Gitlab 설치 디렉토리 생성 및 권한 설정

    # config, logs, data
    mkdir -p /srv/gitlab/{config,logs,data}
    chmod -R 777 /srv/gitlab
    chown 1000:1000 /srv/gitlab
    
    cd srv
    chcon -Rv -u system_u *
    chcon -Rv -t container_file_t *
    
    ls -lZ *
    drwxrwxr-x. root root system_u:object_r:container_file_t:s0 config
    drwxr-xr-x. root root system_u:object_r:container_file_t:s0 data
    drwxr-xr-x. root root system_u:object_r:container_file_t:s0 logs
    
  • Gitlab 설치

    docker run --detach --hostname gitlab.redhat2.cccr.local \
    --publish 18443:443 --publish 18080:80 --publish 18022:22 \
    --name gitlab --restart always \
    --volume /srv/gitlab/config:/etc/gitlab \
    --volume /srv/gitlab/logs:/var/log/gitlab \
    --volume /srv/gitlab/data:/var/opt/gitlab \
    gitlab/gitlab-ce:latest

4. Minio

  • Minio 설치 디렉터리 생성

    mkdir /mnt/minio
    chmod -R 777 /mnt/minio
  • Minio 설치

    docker run -itd -p 9000:9000 \
    --name minio1 --privileged=true \
    -e "MINIO_ACCESS_KEY=minioadmin" \
    -e "MINIO_SECRET_KEY=minioadmin" \
    -v /mnt/minio:/data minio/minio server /data
  • Minio dash-board 접속 후, quay 전용 디렉터리 생성

5. quayconfig 기반 Red Hat Quay 설정

  • 사전에 다른 Quay 컨테이너를 사용하여 사용할 Quay 구성 파일(config.yaml)과 인증파일(security_scanner.pem) 생성

  • Quay가 어떤 Redis, MySQL, Gitlab, Clair와 연동할 것인지, Quay Web Console 접속할 시 사용할 ID, Password 등에 대해 정의

  • 구성파일 생성용 Quay 컨테이너 생성

    docker run --privileged=true -p 28443:8443 -d quay.io/redhat/quay:v3.2.1 config password
  • Docker process가 ipv4의 ip를 갖도록 설정 (optional)

    vi /etc/sysctl.conf 
    net.ipv4.ip_forward = 1
    
    systemctl restart network
  • quay 구성 도구가 실행중인 컨테이너의 URL(ex-https://quay.redhat2.cccr.local:28443/) 접속하여 새로운 quayconfig 생성

6. quayconfig 생성 ( Dashboard에서 진행 )

  • Setup (DB 정보 입력)

    • Database Type : MySQL
    • Database Server : 192.168.100.10:3306
    • Username : quay
    • Password : quay
    • Database Name : quay
  • Super User 생성

  • Server Configuration

    • Server Hostname : quay.redhat2.cccr.local
  • Time Machine

    • 따로 설정하지 않음
  • Redis

    • Redis Hostname : 192.168.100.10
    • Redis Port : 6379
  • Repository Mirroring

    • Enable Repository Mirroring 선택
  • Security Scanner

    • Enable Security Scanning 선택

    • Security Scanner Endpoint : http://clair.redhat2.cccr.local:6060 ( clair container의 endpoint 기입 )

    • Authentication Key 다운로드

      • Assign New Key
      • key name : security_scanner Service Key
      • 다운로드 한 키는 Clair 컨테이너의 /var/lib/clair-config에 복사
  • Application Registry

    • Enable App Registry 선택
  • Registry Protocol Settings

    • Restrict V1 Push Support 선택 해제
  • Minio 설정

    • Storage Engine : Red Hat Openshift Container Storage (NooBaa S3)
    • NooBaa Server Hostname : 192.168.100.10
    • Custom Port(optional) : 9000
    • Access Key : minioadmin
    • Secret Key : minioadmin
    • Bucket Name : quay
    • Storage Directory : /registry
  • Gitlab

  • 다음 단계로 넘어가 설정 정보가 포함된 File을 local에 다운로드

7. Quay 설치 및 배포

  • 앞서 만든 minio, quay (설정 컨테이너), gitlab, redis, mysql 컨테이너 확인

    docker ps
    
    CONTAINER ID        IMAGE                                             COMMAND                  CREATED             STATUS                    PORTS                                                                  NAMES
    4720d202d0e3        minio/minio                                       "/usr/bin/docker-e..."   18 minutes ago      Up 18 minutes             0.0.0.0:9000->9000/tcp                                                 minio1
    2575c3050175        quay.io/redhat/quay:v3.2.1                        "/quay-registry/qu..."   31 minutes ago      Up 31 minutes             7443/tcp, 8080/tcp, 0.0.0.0:28443->8443/tcp                            kind_pare
    7a33ff0ce108        gitlab/gitlab-ce:latest                           "/assets/wrapper"        37 minutes ago      Up 37 minutes (healthy)   0.0.0.0:18022->22/tcp, 0.0.0.0:18080->80/tcp, 0.0.0.0:18443->443/tcp   gitlab
    626c3eb9fd77        registry.access.redhat.com/rhscl/redis-32-rhel7   "container-entrypo..."   44 minutes ago      Up 44 minutes             0.0.0.0:6379->6379/tcp                                                 stupefied_dubinsky
    5905964d5a75        registry.access.redhat.com/rhscl/mysql-57-rhel7   "container-entrypo..."   46 minutes ago      Up 46 minutes             0.0.0.0:3306->3306/tcp                                                 mysql
  • Quay에서 사용할 디렉토리를 생성

    mkdir -p /mnt/quay/{config, storage}
  • Quay 설정파일 옮기기

  • 앞서 local PC에 다운 받은 quay-config.tar.gz를 Quay vm 으로 이동

    scp quay-config.tar.gz [email protected]:/mnt/quay/config/
  • Quay vm 에서 quay-config.tar.gz 압축 해제

    cd /mnt/quay/config
    
    tar xvf quay-config.tar.gz
    
    chcon -Rv -u system_u *.yaml
    chcon -Rv -t container_file_t *
  • Quay 설치 및 배포

  • 이 때, 컨테이너에 gitlab host 정보를 추가하여 builderworker가 quay와 같은 서버에 설치될 경우에 발생할 수 있는 no_such_host 에러를 방지

    docker run --restart=always -p 443:8443 -p 80:8080 \
    --add-host gitlab.redhat2.cccr.local:192.168.100.10 \
    --sysctl net.core.somaxconn=4096 \
    --privileged=true \
    -v /mnt/quay/config:/conf/stack:Z \
    -v /mnt/quay/storage:/datastorage:Z \
    -d quay.io/redhat/quay:v3.2.1
  • Quay Super User 계정 ( ID: admin, Password: password )으로 Quay 콘솔(quay.redhat2.cccr.local)에 로그인하여 확인

8. Mirror Worker와 Builder 실행

  • Mirror worker 실행

    docker run -d --name mirroring-worker -v /mnt/quay/config:/conf/stack:Z \
    -d quay.io/redhat/quay:v3.2.1 repomirror
  • Builder 실행

  • 환경 변수로 SERVER를 사용하여 worker가 Red Hat Quay에 접근할 수 있는 Host이름을 지정해야 하며, TLS를 사용하지 않는 경우 ws 파라미터와 함께 Port를 명시해야 함

    docker run --restart on-failure \
    -e SERVER=ws://192.168.100.10:80 \
    --privileged=true \
    -v /var/run/docker.sock:/var/run/docker.sock:Z \
    -d quay.io/redhat/quay-builder:v3.2.1



Clair 설치

  • Openshift에서 Clair는 컨테이너 이미지를 스캔하여 취약점을 검사하고 수정 사항을 제안하는 역할을 수행
  • Clair를 실행하려면 Database가 필요
  • Clair의 Database로 MySQL은 지원하지 않으므로 본 프로젝트에서는 PostgreSQL로 구성

1. Clair 설치 작업 디렉터리 생성

  • 작업 디렉터리 : /var/lib/clair-config
    mkdir -p /var/lib/clair-config && cd /var/lib/clair-config
    chmod 777 /var/lib/clair-config

2. PostgreSQL 설치

  • pgsql Container

    docker run -d -p 5432:5432 --name pgsql -e POSTGRES_PASSWORD=mysecretpassword \
    -e POSTGRES_HOST_AUTH_METHOD=trust postgres
  • postgres Container

    docker run --rm --link pgsql:postgres postgres \
    sh -c 'echo "create database clairtest" | psql -h \
    "$POSTGRES_PORT_5432_TCP_ADDR" -p \
    "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'

3. Clair Image Pull ( Security-enabled )

  • Clair 설정 파일( config.yaml )생성

    vi /var/lib/clair-config/config.yaml
    # Example of clair config.yaml 
    clair:
    database:
        type: pgsql
        options:
        source: postgresql://[email protected]:5432/clairtest? sslmode=disable
        cachesize: 16384
    api:
        healthport: 6061
        port: 6062
        timeout: 900s
        paginationkey:
    updater:
        interval: 6h
        enabledupdaters:
        - debian
        - ubuntu
        - rhel
        - oracle
        - alpine
        - suse
        notifier:
        attempts: 3
        renotifyinterval: 1h
        http:
            endpoint: http://quay.redhat2.cccr.local/secscan/notify
            proxy: http://localhost:6063
    jwtproxy:
    signer_proxy:
    enabled: true
    listen_addr: :6063
    ca_key_file: /certificates/mitm.key  
    ca_crt_file: /certificates/mitm.crt  
    signer:
        issuer: security_scanner
        expiration_time: 5m
        max_skew: 1m
        nonce_length: 32
        private_key:
        type: autogenerated
        options:
            rotate_every: 12h
            key_folder: /clair/config/
            key_server:
            type: keyregistry
            options:
                registry: http://quay.redhat2.cccr.local/keys/
    verifier_proxies:
    - enabled: true
        listen_addr: :6060
        verifier:
        audience: http://clair.redhat2.cccr.local:6060
        upstream: http://localhost:6062
        key_server:
            type: keyregistry
            options:
            registry: http://quay.redhat2.cccr.local/keys/
  • local에서 Quay vm의 /var/lib/clair-config 로 security_scanner.pem 파일 이동

  • Clair 관련 파일 권한 설정

    # config.yaml
    chcon -Rv -u system_u *.yaml
    # security_scanner.pem
    chcon -Rv -u system_u *.pem
    # Context Change
    chcon -Rv -t container_file_t *

4. Clair 컨테이너 설치 및 배포

  • jwt(Json Web Token) : Json 포맷을 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 Web Token

    docker run -d --restart=always -p 6060:6060 -p 6061:6061 \
    --add-host quay.redhat2.cccr.local:192.168.100.10 \
    --privileged=true -v /var/lib/clair-config:/clair/config \
    quay.io/redhat/clair-jwt:v3.2.1



Quay 웹 콘솔에서 Docker Build Test

1. Quay 로 Docker 이미지 pull

  • Quay Domain Name : quay.redhat2.cccr.local
  • ubi7 이라는 Docker 이미지를 사용하여 test 진행
  • 아래 명령어 실행 시, Quay 에서 repositories에서 /admin/ubi7 확인 가능
    docker pull ubi7
    
    # Namespace : admin, Repository : ubi7, Version : v0.1
    docker tag ubi7 quay.redhat2.cccr.local/admin/ubi7:v0.1
    docker push quay.redhat2.cccr.local/admin/ubi7:v0.1

2. 레포지토리에 Robot 계정 생성

  • Quay 콘솔을 통해 Repositories-> /admin/ubi7-> Setting-> Robot 계정 생성
  • Robot에게 ubi7 Repository에 대한 Read 권한 부여

3. Docker 이미지 Build

  • Dockerfile 준비

    ### Dockerfile
    
    FROM quay.redhat2.cccr.local/admin/ubi7:v0.1
    RUN echo "Hello world" > /tmp/hello_world.txt
    CMD ["cat", "/tmp/hello_world.txt"\
  • Repository-> Build Triggers -> Start New Build -> Select file -> Dockerfile 에 앞서 만든 Dockerfile 선택 -> Start Build

  • DockerBuild 성공

4. 이미지 보안성 검사

  • DockerBUild 성공 화면에서 설정(톱니바퀴)에서 Tag 이름을 v0.2로 수정
  • Tag History 확인 및 빌드된 이미지의 보안성 체크 확인

  • tag 수정한 Docker 컨테이너가 잘 작동하는지 확인

    docker run -it quay.redhat2.cccr.local/admin/ubi7:v0.2
    Hello world
    
    docker ps -a
    CONTAINER ID        IMAGE                                             COMMAND                  CREATED             STATUS                     PORTS                                                                  NAMES
    268c03123b2a        quay.redhat2.cccr.local/admin/ubi7:v0.2           "cat /tmp/hello_wo..."   2 minutes ago       Exited (0) 2 minutes ago                                                                          infallible_wozniak



Openshift 내부 Registry에서 Quay Build Test

1. Quay DNS 설정

  • bastion 노드를 Quay 의 DNS 서버로 설정하여 Disconnected 환경의 OCP Node와 통신이 가능하도록 설정
    vi /etc/resolv.conf 
    
    server 10.10.10.17
    server 8.8.8.8

2. Quay 노드에서 oc 명령어 활성화

  • Bastion node 에서 활성화 했던 것과 동일한 방법으로 진행

  • 단, Quay 노드는 인터넷이 되는 환경에서 사용되므로 oc command를 바로 다운 가능

  • 명령으로 사용가능 하도록 환경변수 설정 경로 하위에 oc와 kubectl 기입

    wget https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.4.17/openshift-client-linux-4.4.17.tar.gz
    
    tar -xvf openshift-client-linux-4.4.17.tar.gz 
    README.md
    oc
    kubectl
    
    cp ./oc /usr/local/bin/
    cp ./kubectl /usr/local/bin/
    
    oc version
    Client Version: 4.4.17
    Server Version: 4.4.17
    Kubernetes Version: v1.17.1+20ba474
    
    kubectl version
    Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0-4-g38212b5", GitCommit:"d89e458c3dff553f9a732b282830bfa9b4e0ab9b", GitTreeState:"clean", BuildDate:"2020-08-10T08:45:51Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"linux/amd64"}
    Server Version: version.Info{Major:"1", Minor:"17+", GitVersion:"v1.17.1+20ba474", GitCommit:"20ba474", GitTreeState:"clean", BuildDate:"2020-08-10T09:03:30Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"linux/amd64"}
    
    # /root 디렉터리에 kubeconfig 파일 위치하기 
    export KUBECONFIG=/root/kubeconfig
    
    # 이제 oc 명령어를 사용할 수 있음
    oc whoami
    kube:admin
    
    oc get nodes
    NAME                           STATUS     ROLES    AGE   VERSION
    master-1.redhat2.cccr.local    Ready      master   25d   v1.17.1+20ba474
    master-2.redhat2.cccr.local    Ready      master   25d   v1.17.1+20ba474
    ...



Allowing Pods to reference images from other secured registries

1. ~/.docker/config.json 확인

  • Docker clients용 .dockercfg ( $HOME/.docker/config.json )은 이전에 보안 또는 안전하지 않은 레지스트리에 로그인 한 경우 인증 정보를 저장하는 Docker credentials 파일

  • OCP의 내부 레지스트리가 아닌 보안 컨테이너 이미지를 가져오려면 Docker Credentials에서 pull secret을 생성하여 서비스 계정에 추가해야 함

    cd .docker/
    cat config.json 
    {
        "auths": {
            "quay.io": {
                "auth": "cmVkaGF0K3F1YXk6TzgxV1NIUlNKUjE0VUFaQks1NEdRSEpTMFAxVjRDTFdBSlYxWDJDNFNEN0tPNTlDUTlOM1JFMTI2MTJYVTFIUg=="
            },
            "quay.redhat2.cccr.local": {
                "auth": "YWRtaW46cGFzc3dvcmQ="
            }
        }
    }

2. secret와 link 생성

  • secret 생성
    oc create secret generic 'secret 이름' \
    --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson
    
    secret/test created
    
  • secret link 설정
    # default : 기본 서비스 계정
    oc secrets link default 'secret 이름' --for=pull
    # build 이미지를 push & pull 하는데 secret을 사용하려면 Pod 내부에 Secret을 마운트 하여 사용
    oc secrets link builder 'secret 이름'

3. cluster yaml 파일 수정

  • OCP 콘솔 -> Search -> Image (Config) -> Cluster -> YAML 에 아래 내용 기입

    # Exmaple
    allowedRegistriesForImport:
    	- domainName: quay.redhat2.cccr.local
    		insecure: true
    registrySources:
    	insecureRegistries:
    	- quay.redhat2.cccr.local




참고문헌

https://coreos.com/quay-enterprise/docs/latest/clair.html