2020/05/20
openprojectをGKEで導入する
概要
Titleの通りですが、OSSのプロジェクト管理ツールであるopenprojectをkubernetes上にデプロイをして運用を開始しました。
以前はasanaを使っていたのですが、セキュリティ的な観点やコストなどを検討した結果こちらに載せ替えることにしました。
実は別プロジェクトで、運用実績があるのですが、使い勝手がよかったため、本プロジェクトにも導入することを決めました。
実施事項
- VPCを追加
- k8s clusterで利用するため、pod用とservice用に2つのセカンダリIP Rangeを作成するのがポイント
- Cloud NATを作成
- Google Cloud Routerを作成して、No.1で作ったSubnetに適用します
- Elastic IP AddressをNAT用に作成します
- k8s clusterを作成します
- 限定公開クラスタにして、特定のIPからしかk8sのmasterにアクセスできないようにします
- こうしておくと、勝手にNo.2で作成したNATが適用され、このクラスタ内部から、インターネットへの外向きの通信ができるようになります
- このクラスタには他にも種々のmanagement用サービスをdeployするため、1vCPU + 6GBのマシン3台構成をイニシャルの設定としておきます
- ネットワークタグを指定しておき、後々Firewallの設定を管理し易くしておきます
- こうすることで、このネットワークタグが自動で、ノードのインスタンスにつきます
- openprojectをk8sにデプロイします
k8sのデプロイ内容詳細
事前準備
- openproject用のpostgresql及びupload file用のcompute diskを作成しておきます。(それぞれ20GBと10GBほど)
- openprojectのweb server(nginx)のためのelastic ip addressを作成しておきます。
- sendgridでapi keyを発行しておきます。(メール送信用です)
k8sへのデプロイ設定ファイル及び順序
namespace
apiVersion: v1
kind: Namespace
metadata:
name: openproject
secrets
apiVersion: v1
kind: Secret
metadata:
name: openproject
namespace: openproject
type: Opaque
data:
secret-key-base: <base64-encoded-string-here>
---
apiVersion: v1
kind: Secret
metadata:
name: postgresql
namespace: openproject
type: Opaque
data:
password: <base64-encoded-string-here>
---
apiVersion: v1
kind: Secret
metadata:
name: sendgrid
namespace: openproject
type: Opaque
data:
# 事前準備で作成した sendgrid の secret keyをbase64エンコードします
apiKey: <base64-encoded-string-here>
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: internal-tls
namespace: openproject
data:
# nginxで使うsslのcrtファイルの中身をbase64エンコードします
tls_certificate_chain: <base64-encoded-string-here>
# nginxで使うsslのkeyファイルの中身をbase64エンコードします
tls_certificate_key: <base64-encoded-string-here>
# you can generate tls_dhparam by `openssl dhparam 2048 -out tls_dhparam`
tls_dhparam: <base64-encoded-string-here>
config map
apiVersion: v1
kind: ConfigMap
metadata:
name: openproject
namespace: openproject
data:
rails-cache-store: "memcache"
cache-server: "memcached:11211"
database-url: "postgres://openproject:<psqlpasswordhere>@postgresql/openproject"
smtp-domain: "openproject.example.com"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: postgresql
namespace: openproject
data:
user: openproject
db-name: openproject
postgresql
apiVersion: v1
kind: PersistentVolume
metadata:
name: openproject-postgresql
spec:
storageClassName: openproject-postgresql
capacity:
storage: 20Gi # <- 事前準備で作成した compute disk のサイズ
accessModes:
- ReadWriteOnce
gcePersistentDisk:
pdName: openproject-postgresql # <- 事前準備で作成した compute disk の名前
fsType: ext4
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgresql
namespace: openproject
spec:
storageClassName: openproject-postgresql
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgresql
namespace: openproject
spec:
replicas: 1
selector:
matchLabels:
app: postgresql
template:
metadata:
name: postgresql
labels:
app: postgresql
node: management-suite
spec:
containers:
- name: postgresql
image: postgres:9.5.6-alpine
env:
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: postgresql
key: user
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql
key: password
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: postgresql
key: db-name
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- name: postgres
containerPort: 5432
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: postgresql
volumes:
- name: postgresql
persistentVolumeClaim:
claimName: postgresql
---
apiVersion: v1
kind: Service
metadata:
name: postgresql
namespace: openproject
spec:
ports:
- name: postgres
port: 5432
targetPort: postgres
selector:
app: postgresql
memcached
apiVersion: apps/v1
kind: Deployment
metadata:
name: memcached
namespace: openproject
spec:
replicas: 1
selector:
matchLabels:
app: memcached
template:
metadata:
name: memcached
labels:
app: memcached
node: management-suite
spec:
containers:
- name: memcached
image: memcached:1.5.22-alpine
ports:
- containerPort: 11211
protocol: TCP
- containerPort: 11211
protocol: UDP
---
apiVersion: v1
kind: Service
metadata:
name: memcached
namespace: openproject
spec:
ports:
- protocol: TCP
port: 11211
targetPort: 11211
selector:
app: memcached
openproject app
apiVersion: v1
kind: PersistentVolume
metadata:
name: openproject-assets
spec:
storageClassName: openproject-assets
capacity:
storage: 10Gi # <- 事前準備で作成した compute disk のサイズ
accessModes:
- ReadWriteOnce
gcePersistentDisk:
pdName: openproject-assets # <- 事前準備で作成した compute disk の名前
fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: openproject-assets
namespace: openproject
spec:
storageClassName: openproject-assets
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: openproject
namespace: openproject
spec:
replicas: 1
selector:
matchLabels:
app: openproject
template:
metadata:
name: openproject
labels:
app: openproject
node: management-suite
spec:
securityContext:
fsGroup: 1000 # GID of app user
containers:
- name: openproject
image: openproject/community:10.3.1
env:
- name: SECRET_KEY_BASE
valueFrom:
secretKeyRef:
name: openproject
key: secret-key-base
- name: RAILS_CACHE_STORE
valueFrom:
configMapKeyRef:
name: openproject
key: rails-cache-store
- name: OPENPROJECT_CACHE__MEMCACHE__SERVER
valueFrom:
configMapKeyRef:
name: openproject
key: cache-server
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: openproject
key: database-url
- name: EMAIL_DELIVERY_METHOD
value: "smtp"
- name: SMTP_ADDRESS
value: "smtp.sendgrid.net"
- name: SMTP_PORT
value: "2525"
- name: SMTP_DOMAIN
valueFrom:
configMapKeyRef:
name: openproject
key: smtp-domain
- name: SMTP_AUTHENTICATION
value: "login"
- name: SMTP_ENABLE_STARTTLS_AUTO
value: "true"
- name: SMTP_USER_NAME
value: "apikey"
- name: SMTP_PASSWORD
valueFrom:
secretKeyRef:
name: sendgrid
key: apiKey
- name: IMAP_ENABLED
value: "false"
ports:
- name: openproject
containerPort: 8080
volumeMounts:
- mountPath: /var/openproject/assets
name: openproject-assets
volumes:
- name: openproject-assets
persistentVolumeClaim:
claimName: openproject-assets
---
apiVersion: v1
kind: Service
metadata:
name: openproject
namespace: openproject
spec:
ports:
- name: openproject
port: 8080
targetPort: openproject
selector:
app: openproject
nginx
deploymentは割愛しますが、openproject serviceに対してproxyするnginxのDockerを作成して、デプロイします。
secretでデプロイしたtlsの設定ファイルを使用してSSLを有効にします。
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: openproject
spec:
type: LoadBalancer
loadBalancerIP: <XXX.XXX.XXX.XXX> # <- 事前準備で作成した外部IPアドレスの値
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: https
selector:
app: nginx
これらのdeploy後に、内部DNSにAレコードを追加して対応完了です。
関連する記事
[小〜中規模向け]GKEにTiDBをデプロイする
MySQL互換のNewSQLであるTiDBをGKEにデプロイしてみました。
NATS JetStream Controllerを使ってNATSをGKEにデプロイする
helm chartのnackを使って、NATS JetStreamサーバーをデプロイして、Stream/Consumerをk8sリソースとして管理する
GKEにDragonflydbをデプロイする
redis互換のdragonflydbをGKEにデプロイしました
[GKE]Kafka Strimziをアップグレードする
GKEにデプロイしているKafka Strimzi 0.26.0を0.30.0にアップグレードする