참고문서
https://github.com/chequer-io/querypie-deployment
GitHub - chequer-io/querypie-deployment
Contribute to chequer-io/querypie-deployment development by creating an account on GitHub.
github.com
https://docs.querypie.com/ko/installation/installation
설치하기 - QueryPie ACP
QueryPie ACP
docs.querypie.com
QueryPie 최소구성 아키텍처
[Browser]
↓
[QueryPie Web]
↓ (OIDC Redirect)
[Okta]
↓ (ID Token)
[QueryPie]
인프라 권장사항
권장 노드 사양: r5.xlarge (4 vCPU, 32GB RAM)
Kubernetes 버전: 1.24 이상
필요 노드 수: 최소 1개 (프로덕션 환경은 3개 이상 권장)
namespace 생성
kubectl create namespace querypie
MetaDB 설치
MySQL은 QueryPie의 메타데이터를 저장하는 데이터베이스로 사용된다.
# PV 생성
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv
labels:
app: mysql
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /var/lib/mysql
type: DirectoryOrCreate
[root@k8s-master terraform-access-control]# vi pv.yaml
[root@k8s-master terraform-access-control]# k apply -f pv.yaml
persistentvolume/local-pv created
[root@k8s-master terraform-access-control]# k get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
local-pv 50Gi RWO Retain Available <unset> 2s
MySQL statefulset 배포
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: querypie
spec:
selector:
matchLabels:
app: mysql
serviceName: mysql
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: querypie
- name: MYSQL_DATABASE
value: querypie
- name: MYSQL_USER
value: querypie
- name: MYSQL_PASSWORD
value: querypie
resources:
requests:
cpu: "0.5"
memory: "2Gi"
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 50Gi
storageClassName: ""
selector:
matchLabels:
app: mysql
---
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: querypie
labels:
app: mysql
spec:
type: ClusterIP
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
protocol: TCP
name: mysql
[root@k8s-master terraform-access-control]# vi mysql.yaml
[root@k8s-master terraform-access-control]# k apply -f mysql.yaml
statefulset.apps/mysql created
service/mysql created
[root@k8s-master terraform-access-control]# k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql ClusterIP 10.98.161.155 <none> 3306/TCP 72s
[root@k8s-master terraform-access-control]# k get po
NAME READY STATUS RESTARTS AGE
mysql-0 1/1 Running 0 74s
데이터베이스 초기화
kubectl exec -it mysql-0 -n querypie -- mysql -u root -p
# 비밀번호: querypie
DROP DATABASE IF EXISTS querypie;
DROP DATABASE IF EXISTS querypie_log;
DROP DATABASE IF EXISTS querypie_snapshot;
CREATE database querypie CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE database querypie_log CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE database querypie_snapshot CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
GRANT ALL privileges ON querypie.* TO querypie@'%';
GRANT ALL privileges ON querypie_log.* TO querypie@'%';
GRANT ALL privileges ON querypie_snapshot.* TO querypie@'%';
FLUSH PRIVILEGES;
exit
Redis 설치
Redis는 QueryPie의 세션 및 캐시 저장소로 사용된다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: querypie
labels:
app: redis
spec:
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7
imagePullPolicy: IfNotPresent
args: ["--requirepass", "querypie"]
ports:
- containerPort: 6379
protocol: TCP
resources:
limits:
cpu: "0.1"
memory: "1Gi"
volumeMounts:
- name: redis-data
mountPath: /data
restartPolicy: Always
volumes:
- name: redis-data
emptyDir: {} # 파드 재시작 시 데이터 삭제 (캐시 용도면 OK)
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: querypie
labels:
app: redis
spec:
type: ClusterIP
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
protocol: TCP
[root@k8s-master terraform-access-control]# vi redis.yaml
[root@k8s-master terraform-access-control]# k apply -f redis.yaml
deployment.apps/redis created
service/redis created
[root@k8s-master terraform-access-control]# k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql ClusterIP 10.98.161.155 <none> 3306/TCP 19m
redis ClusterIP 10.108.214.141 <none> 6379/TCP 50s
[root@k8s-master terraform-access-control]# k get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mysql-0 1/1 Running 0 19m 10.85.2.94 k8s-node02 <none> <none>
redis-69b5bb5694-bzvb2 1/1 Running 0 54s 10.85.2.95 k8s-node02 <none> <none>
QueryPie 설치
harbor.chequer.io
주소는 QueryPie image를 pull 할 수 있는 사설 레지스트리 주소다.
최초 설치 시 고객사 Harbor 계정을 생성하여 사전에 전달하여 설치할 수 있다.
따라서 kubernetes에 실제적인 설치는 못했지만, 설치 메뉴얼을 남긴다.
# Harbor 레지스트리 인증 정보 등록
kubectl create secret docker-registry querypie-regcred \
--docker-server=harbor.chequer.io \
--docker-username='{harbor-id}' \
--docker-password='{harbor-pw}' \
-n querypie
# QueryPie 환경 설정(querypie.env로 저장)
# Agent Secret (32자리 임의의 문자열)
AGENT_SECRET=01234567890123456789012345678912
KEK=querypie
# QueryPie Meta DB 접속 정보
DB_CATALOG=querypie
DB_HOST=mysql
DB_USERNAME=querypie
DB_PASSWORD=querypie
DB_PORT=3306
# QueryPie Log DB 접속 정보
LOG_DB_CATALOG=querypie_log
LOG_DB_HOST=mysql
LOG_DB_USERNAME=querypie
LOG_DB_PASSWORD=querypie
LOG_DB_PORT=3306
# QueryPie Snapshot DB 접속 정보
ENG_DB_CATALOG=querypie_snapshot
ENG_DB_HOST=mysql
ENG_DB_USERNAME=querypie
ENG_DB_PASSWORD=querypie
ENG_DB_PORT=3306
# Redis 접속 정보
REDIS_NODES=redis:6379
REDIS_PASSWORD=querypie
# 환경설정 파일을 secret로 등록
kubectl create secret generic querypie-secret --from-env-file=querypie.env -n querypie
# Helm Chart 설정
[root@k8s-master terraform-access-control]# helm repo add querypie https://chequer-io.github.io/querypie-deployment/helm-chart
"querypie" has been added to your repositories
[root@k8s-master terraform-access-control]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "querypie" chart repository
[root@k8s-master terraform-access-control]# helm repo list
NAME URL
querypie https://chequer-io.github.io/querypie-deployment/helm-chart
[root@k8s-master terraform-access-control]# helm search repo querypie
NAME CHART VERSION APP VERSION DESCRIPTION
querypie/querypie 1.4.4 11.5.0 A Helm chart for QueryPie
values.yaml 로 아래 파일 저장
appVersion: &version 11.3.0
global:
image:
# -- Default registry used for all images
registry: harbor.chequer.io
# -- Default image tags used for all images
tag: *version
# -- Default image pull policy for all images
pullPolicy: IfNotPresent
# -- Default labels for all resources deployed by the chart
labels: {}
# -- ServiceAccount for QueryPie and QueryPie tools pods
# It is created for authenticating private image registry and AWS API.
# @default -- {}
serviceAccount:
labels: {}
annotations: {}
# -- The name of the secret used for pulling the QueryPie image from the private registry.
# To create, run `kubectl create secret docker-registry querypie-regcred --docker-server=harbor.chequer.io --docker-username=admin --docker-password=your-password`
imagePullSecrets:
- name: querypie-regcred
querypie:
# -- Labels used for QueryPie pods.
labels: {}
# -- Annotations used for QueryPie pods.
annotations: {}
tolerations: {}
# -- NodeSelector for QueryPie pods
nodeSelector: {}
replicas: 1
# -- PodManagementPolicy for QueryPie pods. OrderedReady is fine for most cases, but Parallel is also good for large-scale deployments.
podManagementPolicy: Parallel
image:
# -- (string) Registry used for the QueryPie image. If not set, the global registry will be used.
registry:
# -- (string) Tag used for the QueryPie image. If not set, the global tag will be used.
tag:
# -- (string) PullPolicy used for the QueryPie image. If not set, the global pullPolicy will be used.
pullPolicy:
# -- Repository used for the QueryPie image. (required)
repository: querypie/querypie
ingress:
# -- (bool) If true, Ingress resource for QueryPie will be created.
enabled: true
labels: {}
# -- Annotations used for the Ingress resource.
# It is useful when you want to enable controller-specific feature for the Ingress resource.
annotations: {}
# -- (string) Class used for the Ingress resource. If not set, the default class will be used.
ingressClassName: ""
# -- Hostname used for the Ingress resource. If not set, every hostname will be accepted.
host: querypie.querypie.io #실제 설정된 url 입력
# -- Extra paths used for the Ingress resource.
# It is mostly used for redirecting HTTP to HTTPS if the ingress controller does not support redirect by default.
proxyService:
# -- Create a service resource for QueryPie Agent connections.
# Basically, it opens 9000/tcp port for the QueryPie Agent, and 40000~/tcp for the Agentless connections.
enabled: true
labels: {}
# -- Annotations used for the Service resource.
# It is useful when you want to enable controller-specific feature for the Service resource.
annotations: {}
type: LoadBalancer
loadBalancerClass: ""
# -- Set the externalTrafficPolicy to Local is recommended for auditing the real client IP address.
externalTrafficPolicy: "Local"
# -- SessionAffinity is not required for the QueryPie.
sessionAffinity: "None"
updateStrategy:
# -- The strategy used for updating the QueryPie pods.
# It is generally recommended to use the RollingUpdate strategy.
# But if required, you can change it to OnDelete for manual operations.
type: RollingUpdate
resources:
requests:
cpu: "2000m"
memory: 16Gi
limits:
# -- More than 2 CPU cores are recommended.
cpu: "2000m"
# -- More than 16Gi memory is recommended.
memory: 16Gi
logrotator:
image:
# -- (string) Registry used for the Logrotate image. If not set, the global registry will be used.
repository: querypie/logrotate
# -- (string) Tag used for the Logrotate image. If not set, the global tag will be used.
tag: latest
# -- External storage for the QueryPie Object Storage.
externalStorage:
# -- Type of the external storage.
# - none: No external storage.
# - persistentVolumeClaim: using a single Persistent Volume Claim for all QueryPie pods.
type: none
# -- Use a persistent volume claim for the external storage. It will be available if the type is persistentVolumeClaim.
persistentVolumeClaim:
# -- Use an existing Persistent Volume Claim for the external storage.
# If you set this to true, this helm chart will not create a new Persistent Volume Claim.
useExisting: false
# -- The name of the existing Persistent Volume Claim to be used.
claimName: ""
# -- Metadata of the Persistent Volume Claim.
metadata:
annotations: {}
labels: {}
# -- Spec of the Persistent Volume Claim.
spec:
storageClassName: ""
resources:
requests:
storage: 100Gi
# -- It is required to have ReadWriteMany access mode on production.
accessModes:
- ReadWriteMany
# -- Extra environment variables used for the QueryPie pods.
# This is useful for experimental features, debugging, workaround, and so on.
# for example:
# API_JVM_HEAPSIZE: '2g' will set the JVM heap size to 2GB.
extraEnvs: {}
tools:
image:
# -- Registry used for the QueryPie tools image. If not set, the global registry will be used.
repository: querypie/querypie-tools
config:
# -- External URL that users use to access the QueryPie via web.
# Specify the scheme, hostname, and port is required.
externalURL: "https://querypie.querypie.io" #실제 설정된 url 입력
secretName: "querypie-secret"
database:
querypie:
# -- The maximum number of connections that QueryPie can use for "metastore" purposes.
connectionPoolSize: 20
dac:
# -- This setting is used to ignore simple queries sent by client tools such as DataGrip.
# Please refer to the commented-out example below.
skipCommandConfigData: "{}"
# skipCommandConfig: |
# {
# "mysql": [
# "^(/\\*.*?\\*/)?\\s*SELECT\\s+@@session\\s*\\.\\s*\\w+\\s*$",
# "^(/\\*.*?\\*/)?\\s*SET\\s+session\\s+transaction\\s+\\w+(\\s+\\w+)*\\s*$",
# "^(/\\*.*?\\*/)?\\s*SET\\s+net_write_timeout\\s*=\\s*\\d+\\s*$",
# "^(/\\*.*?\\*/)?\\s*SELECT\\s+database\\s*\\(\\s*\\)\\s*$",
# "^(/\\*.*?\\*/)?\\s*SET\\s+SQL_SELECT_LIMIT\\s*=\\s*\\w+$",
# "^SHOW\\s+VARIABLES\\s+LIKE\\s+'aurora\\\\_version'\\s*$",
# "^SELECT\\s+version\\s*\\(\\s*\\)\\s*,\\s*@@version_comment\\s*,\\s*database\\s*\\(\\s*\\)\\s*$",
# "^SET\\s+autocommit\\s*=\\s*\\d+$",
# "^(/\\*.*?\\*/)\\s*SELECT\\s+((@@session\\s*\\.\\s*|@@)\\w+(\\s+AS\\s+\\w+)?(\\s*,\\s*)?)+\\s*$"
# ]
# }
# -- The path where the skip command config file will be mounted.
skipCommandConfigFile: /app/arisa/skip_command_config.json
# QueryPie 설치
helm upgrade --install poc querypie/querypie --version 1.4.1 -n querypie -f values.yaml
# 데이터베이스 마이그레이션
kubectl exec -it deployments/poc-querypie-tools -n querypie -- /app/script/migrate.sh runall
# 라이선스 등록
kubectl port-forward -n querypie deploy/poc-querypie-tools 8050:8050 &
curl -X POST http://127.0.0.1:8050/license/upload -F file=@license.crt
[License] Upload: Success # 결과
# port-forward 종료
jobs
kill %1
# README.md
## QueryPie Deployment (PoC)
- Helm 기반 QueryPie 배포 구성
- Okta OIDC 연동 설계 및 Terraform IaC 구현
- Private Harbor Registry ImagePullSecret 구성
### Known Limitation
- QueryPie container images are hosted in a private registry (harbor.chequer.io)
- Image pull requires vendor-provided credentials
- Without registry credentials, Pods remain in ErrImagePull state'Okta+QueryPie+k8s' 카테고리의 다른 글
| Okta + SAML → QueryPie 로그인 (0) | 2026.01.06 |
|---|---|
| QueryPie ACP Community Edition 구축 (0) | 2026.01.05 |
| Okta OIDC Application 생성 (0) | 2025.12.30 |
| Okta User 생성 + Group 맵핑 자동화 (0) | 2025.12.29 |
| Okta IAM 자동화 (1) | 2025.12.29 |